Compare commits

...

798 Commits

Author SHA1 Message Date
akwizgran 0134f5da14 Upgrade some test dependencies. 2021-04-30 14:55:08 +01:00
akwizgran 77ed15311c Raise target API level to 30, upgrade build tools to 30.0.3. 2021-04-30 14:51:49 +01:00
akwizgran 3d72557618 Merge branch '1962-connect-via-bt-backend' into 'master'
Implement connect via Bluetooth backend

Closes #1962

See merge request briar/briar!1412
2021-04-27 12:27:55 +00:00
Daniel Lublin e2a11d42f8 Implement backend for connect via bluetooth 2021-04-27 14:15:10 +02:00
akwizgran 0f5ea6ae66 Merge branch 'translation-update-script' into 'master'
Add script to update Android app translations

See merge request briar/briar!1442
2021-04-27 11:09:24 +00:00
akwizgran 5b2c9b85f9 Merge branch 'prevent-double-pipelines' into 'master'
Avoid duplicate CI pipelines running at the same time

See merge request briar/briar!1443
2021-04-27 11:08:13 +00:00
Torsten Grote 94921230d9 Avoid duplicate CI pipelines running at the same time
Docs:
https://docs.gitlab.com/ee/ci/yaml/README.html#switch-between-branch-pipelines-and-merge-request-pipelines
https://docs.gitlab.com/ee/ci/yaml/README.html#avoid-duplicate-pipelines
2021-04-26 15:37:16 -03:00
Torsten Grote 34788356e6 Add script to update Android app translations
add German and Spanish (incl. video) play store listing
2021-04-26 15:14:06 -03:00
akwizgran 2f719d7f2c Bump version numbers for 1.3.2 release. 2021-04-26 13:50:35 +01:00
akwizgran eb2e8d75f4 Enable features for 1.3 release. 2021-04-26 13:45:53 +01:00
akwizgran 338d288290 Update translations. 2021-04-26 13:43:33 +01:00
Torsten Grote 03fe1a2d2c Merge branch '1743-huawei-app-launch' into 'master'
Add button for opening Huawei battery settings during setup

See merge request briar/briar!1441
2021-04-23 13:54:55 +00:00
akwizgran ade48c7bea Merge branch 'fastlane-metadata-upload' into 'master'
Update Google play listing and language mappings

See merge request briar/briar!1440
2021-04-23 13:43:10 +00:00
akwizgran 4a8d89e2bb Add button for opening Huawei battery settings during setup. 2021-04-23 14:25:24 +01:00
Torsten Grote 0fed1681ed Google play listing now available in:
* Persian
* Galician
* Lithuanian
* Turkish
* Chinese (Simplified)
2021-04-23 10:22:27 -03:00
akwizgran 93ad483066 Merge branch 'fastlane-metadata-upload' into 'master'
Update Play Store listing and add Catalan translation

See merge request briar/briar!1439
2021-04-23 10:10:08 +00:00
Torsten Grote d995e73996 Update Play Store listing and add Catalan translation 2021-04-22 14:06:37 -03:00
Torsten Grote 1d271bab18 Merge branch '1914-create-viewmodels-directly-after-injection' into 'master'
Create ViewModels directly after injection

Closes #1914

See merge request briar/briar!1432
2021-04-22 14:59:05 +00:00
Torsten Grote a9d2aa9366 Merge branch '1883-resource-ids-will-be-non-final' into 'master'
Replace switch statements with resource ids with if-then-else

Closes #1883

See merge request briar/briar!1438
2021-04-22 13:34:35 +00:00
Sebastian Kürten 2a48d43e5b Create ViewModels directly after injection 2021-04-22 15:31:55 +02:00
Sebastian Kürten 0a4e23118a Replace switch statements with resource ids with if-then-else 2021-04-22 15:19:11 +02:00
akwizgran 528a15962f Merge branch 'fastlane-metadata' into 'master'
Make Google Play descriptions translatable

See merge request briar/briar!1437
2021-04-22 13:00:13 +00:00
Torsten Grote 0a0cc4e79c Extend full description 2021-04-22 09:50:16 -03:00
Torsten Grote 2b3ba42d70 Make Google Play descriptions translable 2021-04-21 13:35:10 -03:00
akwizgran 9465331ece Merge branch '1999-bluetooth-killed-activity-fix' into 'master'
Reset plugin assignments when starting AddNearbyContactIntroFragment

Closes #1999

See merge request briar/briar!1434
2021-04-21 15:57:17 +00:00
akwizgran b0d86bef3e Merge branch 'scheduled-tests' into 'master'
Run bridge tests in scheduled nightly tests (and fix merge pipelines)

See merge request briar/briar!1431
2021-04-21 13:55:48 +00:00
Torsten Grote a28a2360f1 Merge branch 'remove-redundant-casts' into 'master'
Remove a few redundant casts

See merge request briar/briar!1436
2021-04-21 12:52:04 +00:00
Torsten Grote f7a957150e Tweak CI rules for optional tests
so they are not needed for merge requests
2021-04-21 09:49:11 -03:00
Torsten Grote 67bd065bc3 Allow manual emulator tests in all situations 2021-04-21 09:48:59 -03:00
Torsten Grote 5a3a12767c Increase SetupActivity timeout in PromoVideoTest as the current one doesn't seem to be sufficient 2021-04-21 09:48:58 -03:00
Torsten Grote 2f86bc312c Catch UnableToTakeScreenshotException to make CI more stable 2021-04-21 09:48:58 -03:00
Torsten Grote f0fcadfaf4 Also run optional bridge test with schedules 2021-04-21 09:48:57 -03:00
akwizgran a9d88c849a Merge branch '1961-connect-via-bt-ui' into 'master'
Simple version of Connect via Bluetooth UI

See merge request briar/briar!1398
2021-04-21 11:57:53 +00:00
Sebastian Kürten 7397efca80 Remove a few redundant casts 2021-04-21 13:53:53 +02:00
Torsten Grote 17bd6f9a33 Merge branch '1778-onboarding-tap-target' into 'master'
Wait for layout before showing onboarding tap target

Closes #1778

See merge request briar/briar!1435
2021-04-21 11:45:19 +00:00
akwizgran 2d4e7a9fb0 Wait for layout before showing onboarding tap target. 2021-04-21 12:20:21 +01:00
Torsten Grote 0266da993d Reset plugin assignments when starting AddNearbyContactIntroFragment 2021-04-20 14:38:58 -03:00
Torsten Grote ea5280713f Address review feedback for Connect via Bluetooth UI 2021-04-20 14:24:05 -03:00
Torsten Grote 0b89d29c7d Reset BluetoothPlugin reference
When it is assigned before we are signed-in in (like when returning to a killed activity), it would be null and without a reset, we would consider Bluetooth to not be supported.
2021-04-20 14:23:07 -03:00
Torsten Grote 688bac77a8 Use a feature flag to hide connect via Bluetooth option 2021-04-19 11:36:35 -03:00
Torsten Grote c736bf7c06 Move Connect via Bluetooth UI into DialogFragment
so it can stay active when leaving the context to enable location or permissions
2021-04-19 11:08:02 -03:00
Torsten Grote 539730f8ec Show dialog when permission was denied for good 2021-04-19 11:07:21 -03:00
Torsten Grote a9c4669c75 Simple version of Connect via Bluetooth UI 2021-04-19 11:07:20 -03:00
Torsten Grote 4c11f93ee2 Merge branch '1973-make-use-of-handle-exception' into 'master'
Make more use of DbViewModel#handleException()

Closes #1973

See merge request briar/briar!1427
2021-04-16 17:29:20 +00:00
Sebastian Kürten f8dba6fd7f Add static version of DbViewModel#handleException() in UiUtils 2021-04-15 19:34:14 +02:00
Sebastian Kürten 419247074f Make more use of DbViewModel#handleException() 2021-04-15 17:53:53 +02:00
akwizgran 2ddb7b5b64 Merge branch '1944-update-contact-list-when-changing-aliases' into 'master'
Broadcast ContactAliasChangedEvent to update contact list

Closes #1944

See merge request briar/briar!1425
2021-04-15 15:35:46 +00:00
akwizgran c14b59661e Merge branch 'fix-settings-test' into 'master'
Fix SettingsActivityScreenshotTest and enable scheduled emulator tests

See merge request briar/briar!1429
2021-04-15 15:30:31 +00:00
akwizgran d70d27e665 Merge branch '804-self-destructing-messages' into 'master'
Merge 'Self-destruct timer for messages' to master

Closes #1863

See merge request briar/briar!1396
2021-04-15 15:24:19 +00:00
akwizgran 8991762b0c Final code review nitpicks. 2021-04-15 16:12:38 +01:00
akwizgran 2fc6741c99 Remove redundant method. 2021-04-15 16:03:01 +01:00
akwizgran 1075af73f2 Change default timer duration to 7 days. 2021-04-15 11:54:48 +01:00
Torsten Grote 8671229f76 Merge branch '1672-speed-dial-crash' into 'master'
Close the speed dial to prevent a crash

Closes #1672

See merge request briar/briar!1430
2021-04-14 17:22:06 +00:00
akwizgran 0fb67583ff Close the speed dial to prevent a crash. 2021-04-14 18:10:39 +01:00
Torsten Grote 2fc0fd17a2 Fix SettingsActivityScreenshotTest 2021-04-14 11:43:31 -03:00
Torsten Grote f185860213 Allow emulator tests to run also on a schedule
Also do 1 retry in case of failure
2021-04-14 10:57:49 -03:00
akwizgran 8ffcdbfc21 Merge branch 'sort-blogposts' into 'master'
Sort the loaded posts, like FeedViewModel already does

See merge request briar/briar!1428
2021-04-14 10:14:34 +00:00
Daniel Lublin 6a38e2cca8 Sort the loaded posts, like FeedViewModel already does 2021-04-14 12:02:02 +02:00
Sebastian Kürten 10d9d78ca8 Broadcast ContactAliasChangedEvent to update contact list 2021-04-14 07:43:50 +02:00
Torsten Grote 03a68038e7 Merge branch 'v3-address-for-feedback-and-crash-reports' into 'master'
Use a v3 hidden service for receiving feedback and crash reports

See merge request briar/briar!1426
2021-04-13 17:01:58 +00:00
akwizgran fabefcdf4b Use a v3 hidden service for receiving feedback and crash reports. 2021-04-13 17:50:36 +01:00
Sebastian Kürten 9e4d8ecddf Make introducees send auto-declines even if reponse already received 2021-04-13 08:49:04 -03:00
Sebastian Kürten 1dffbfd8dc Add two tests for auto-declines happening after response already received 2021-04-13 08:49:04 -03:00
Sebastian Kürten 950db5a87a Assert that IntroductionManager return true for canIntroduce() 2021-04-13 08:49:04 -03:00
Sebastian Kürten 21348d5557 IntroductionManager: don't throw IllegalArgumentException when deleting invisible msgs 2021-04-13 08:49:03 -03:00
Sebastian Kürten eb1a089437 Revert changes to AbstractProtocolEngine
This reverts parts of commit 5d143f8b33adc07d990627036b806a2becea7074.
2021-04-13 08:49:03 -03:00
Sebastian Kürten 17fc81ab7a Re-add integration test that goes through two full introduction cycles 2021-04-13 08:49:03 -03:00
Torsten Grote 1c54fd1101 Don't auto-delete invisible forwarded responses on sender side
They will be visible for the recipient, so send with timer
2021-04-13 08:49:02 -03:00
Sebastian Kürten 263bce38cd Create new test that reproduces #1975 2021-04-13 08:49:02 -03:00
Sebastian Kürten a923c1151c Move setReadFlag() from ConversationClient to ConversationManager 2021-04-13 08:49:02 -03:00
Sebastian Kürten 0bf10a827f Implement auto-declining for self-destructed introductions 2021-04-13 08:49:01 -03:00
Daniel Lublin 49850e4198 Make sure invitation accept msg is linking to shareable 2021-04-13 08:49:01 -03:00
Daniel Lublin 95b437b311 Add test for invitee responding after sharer deleted invitation 2021-04-13 08:49:00 -03:00
Daniel Lublin 7006f765a6 Keep members in subclasses and use getters 2021-04-13 08:49:00 -03:00
Daniel Lublin ec3360400c Assert that expected event is broadcasted 2021-04-13 08:49:00 -03:00
Daniel Lublin 5c41d09c52 Remember when invitation was auto-declined due to deletion
And render differently
2021-04-13 08:48:59 -03:00
Daniel Lublin a7590956fd Auto-decline/auto-delete Forum & Blog sharing invitations/responses 2021-04-13 08:48:59 -03:00
Torsten Grote a581960121 Don't show notification for own auto-decline responses 2021-04-13 08:48:58 -03:00
Torsten Grote dc57a0b925 Use AtomicReference in TestEventListener to store event 2021-04-13 08:48:58 -03:00
Torsten Grote d6082162ab Add a way to check for expected events
and use it for private group auto-declines
2021-04-13 08:48:58 -03:00
Torsten Grote 1801afdbb7 Update support for disappearing messages in real time 2021-04-13 08:48:57 -03:00
akwizgran 458add0c9c Don't advertise support for messaging features that are disabled by flags. 2021-04-13 08:48:57 -03:00
akwizgran f2374eb141 Count sent messages in integration tests. 2021-04-13 08:48:56 -03:00
Torsten Grote 5db5897793 Use stored session metadata instead of fetching it again 2021-04-13 08:48:56 -03:00
Torsten Grote f3d628afa7 Render automatic declines differently in the UI
and show them as they happen via an Event
2021-04-13 08:48:55 -03:00
Torsten Grote 4d3482e40e Remember when declines were automatic due to deletion
so they can be shown differently for sender
2021-04-13 08:48:55 -03:00
Torsten Grote a8cff454ec Add integration tests for auto-deletion of private group invitations and responses 2021-04-13 08:48:55 -03:00
Torsten Grote f66cae4749 Factor out auto-delete integration test code
so we can re-use it in other tests
2021-04-13 08:48:54 -03:00
Torsten Grote aded1daf92 Auto-delete PrivateGroup invitations and responses as well 2021-04-13 08:48:54 -03:00
Torsten Grote aa1ba0d950 Turn 'Learn more' link into a button to have a larger tap area
and a selectable background
2021-04-13 08:48:53 -03:00
Torsten Grote 071010e438 Turn ConversationSettingsLearnMoreDialog into a generic Onboarding fragment 2021-04-13 08:48:53 -03:00
Torsten Grote f6d8e364d6 Update auto-delete onboarding text 2021-04-13 08:48:53 -03:00
akwizgran f1453ed4c4 Show disabled menu item if we support feature but contact doesn't. 2021-04-13 08:48:52 -03:00
akwizgran 3a2146cb03 Don't advertise support for disappearing messages unless flag is enabled. 2021-04-13 08:48:52 -03:00
akwizgran 24eb76de20 Hide disappearing messages menu item unless feature flag is enabled. 2021-04-13 08:48:51 -03:00
akwizgran 693478e0a5 Add feature flag for self-destructing messages. 2021-04-13 08:48:51 -03:00
Torsten Grote bf6be5c5a7 Replace all messages when re-loading
to ensure that messages deleted in the meantime get removed
2021-04-13 08:48:51 -03:00
Torsten Grote a12a639cd3 Remove auto-deleted messages immediately from conversation 2021-04-13 08:48:50 -03:00
Torsten Grote ef37428714 Replace MessagesCleanedUpEvent with ConversationMessagesDeletedEvent 2021-04-13 08:48:50 -03:00
akwizgran 644afe8995 Wait for events to be delivered before continuing with test. 2021-04-13 08:48:50 -03:00
akwizgran c66c428124 Log how long it takes to deliver private messages and attachments. 2021-04-13 08:48:49 -03:00
akwizgran db5b2ea9b6 Remove redundant call to getAutoDeleteTimer(). 2021-04-13 08:48:49 -03:00
akwizgran d84603bce2 Check group counts in AutoDeleteIntegrationTest. 2021-04-13 08:48:48 -03:00
akwizgran b128370299 Include legacy messages when recalculating group count. 2021-04-13 08:48:48 -03:00
akwizgran 240e619248 Delete private messages when their timers expire (needs UI support). 2021-04-13 08:48:48 -03:00
akwizgran c89bde08db Move ConversationManagerImpl to conversation package. 2021-04-13 08:48:47 -03:00
akwizgran 3ecd1c62b8 Set default timer duration to 1 minute for testing. 2021-04-13 08:48:47 -03:00
akwizgran e3c5497283 Update javadoc to explain that a new timer can be set. 2021-04-13 08:48:46 -03:00
akwizgran 4bd8ee8ccf Pass message IDs to cleanup hooks in batches. 2021-04-13 08:48:46 -03:00
akwizgran 43b437af92 Group messages by group ID when fetching them from database. 2021-04-13 08:48:46 -03:00
akwizgran 56e0d62597 Throw an exception if no cleanup hook was registered. 2021-04-13 08:48:45 -03:00
akwizgran d10e5f025d Remove copypasta. 2021-04-13 08:48:45 -03:00
akwizgran b1a80691db Add comment to explain that starting timer may be a no-op. 2021-04-13 08:48:44 -03:00
akwizgran 049aa61e85 Stop the timer if no hook has been registered. 2021-04-13 08:48:44 -03:00
akwizgran 7026361234 Add javadocs for CleanupManager and CleanupHook. 2021-04-13 08:48:44 -03:00
akwizgran 5e30dc5bf4 Simplify deadline comparison logic. 2021-04-13 08:48:43 -03:00
akwizgran 024bfc8ec8 Stop the cleanup timer if the hook returns false. 2021-04-13 08:48:42 -03:00
akwizgran 04e5e8e4d0 Add cleanup manager. 2021-04-13 08:48:38 -03:00
akwizgran 7c5d47733f Query message IDs rather than metadata when only IDs are needed. 2021-04-13 08:46:11 -03:00
Torsten Grote b24f2a1818 Add support for showing auto-delete timers in minutes 2021-04-13 08:46:11 -03:00
Torsten Grote ee6664ce9d Show actual auto-delete timer duration in UI
(only days and hours for now)
2021-04-13 08:46:11 -03:00
Torsten Grote ab434946b5 Show outgoing message status icon in same color as time 2021-04-13 08:46:10 -03:00
Torsten Grote 35e431eb99 Fix bomb icon color
in incoming image messages without text (on old phones)
2021-04-13 08:46:10 -03:00
Torsten Grote aa8cddf509 Get rid of SENDING state and publish new live data in order on UiThread 2021-04-13 08:46:10 -03:00
Torsten Grote c9ede0bfc1 Return LiveData when sending message 2021-04-13 08:46:09 -03:00
Torsten Grote 6ec9a0f2b2 Show warning dialog when auto-delete timer has changed since starting to compose message 2021-04-13 08:46:09 -03:00
Torsten Grote 2f86112801 Add "Tap to learn more" to message bubbles for timer changes 2021-04-13 08:46:09 -03:00
akwizgran c032befe6f Provide clock for UI tests. 2021-04-13 08:46:08 -03:00
akwizgran 55eccde031 Add some comments. 2021-04-13 08:46:08 -03:00
akwizgran 5716820439 Sync acks for initial messages when setting up integration tests. 2021-04-13 08:46:08 -03:00
akwizgran 17d433dd9b Allow time travel in integration tests. 2021-04-13 08:46:07 -03:00
akwizgran 000812bf6d Inject DefaultTaskSchedulerModule.EagerSingletons at startup in headless app. 2021-04-13 08:46:07 -03:00
akwizgran 5e2187a877 Refactor integration tests to allow clock to be replaced. 2021-04-13 08:46:06 -03:00
Sebastian Kürten e10b6334f5 Introduce conversation settings screen 2021-04-13 08:46:06 -03:00
Torsten Grote baa0341727 Create group invitation with read-write transaction
because the AutoDeleteManager needs to change the DB
and otherwise crashes.

Closes #1863
2021-04-13 08:46:06 -03:00
Torsten Grote 814b2b2582 Make view state of text send UI easier to reason about
and fix bugs with bomb badge and hint display
2021-04-13 08:46:05 -03:00
Torsten Grote 56705bde74 Show bomb badge in same style as send button 2021-04-13 08:46:05 -03:00
Torsten Grote dceb38b777 Show a bomb badge on the send button when disappearing messages is active 2021-04-13 08:46:05 -03:00
Torsten Grote 9947a6aa1b Use a different hint in conversation when message will disappear
and keep the hint updated when the auto-delete timer changes
2021-04-13 08:46:04 -03:00
Torsten Grote 7a3be374c8 Broadcast event when auto delete timer is mirrored 2021-04-13 08:46:04 -03:00
Torsten Grote 4ea3ce0e3c Remove mirrored timer texts
as we can't detect reliably if a timer setting was mirrored or manually changed.

Also remove item update optimization from adapter as this can cause issues when items already exist.
2021-04-13 08:46:04 -03:00
Torsten Grote 923185b3f4 Show timer change notices in private conversations 2021-04-13 08:46:03 -03:00
Torsten Grote d91e6c6c1a Allow setting a self-destruct timer
This is a rough prototype of #1837 meant to make testing the UI easier.
2021-04-13 08:46:03 -03:00
akwizgran 1c93a79448 Use Collections.sort() to satisfy Animal Sniffer. 2021-04-13 08:46:03 -03:00
akwizgran e12ad0cd79 Add integration tests for timer mirroring. 2021-04-13 08:46:02 -03:00
akwizgran 8d6bd29b93 Add method for UI and tests to get current timer. 2021-04-13 08:46:02 -03:00
akwizgran f941a73999 Update integration tests. 2021-04-13 08:46:02 -03:00
akwizgran c3057141d8 Don't receive auto-delete timer from remote accept message as introducee. 2021-04-13 08:46:01 -03:00
akwizgran 49080cb64c Hook up incoming messages to the auto-delete manager. 2021-04-13 08:46:01 -03:00
akwizgran 27dbe23914 Mirror the remote auto-delete timer. 2021-04-13 08:46:01 -03:00
akwizgran d7a2de5817 Add integration tests for auto-delete timer. 2021-04-13 08:46:00 -03:00
akwizgran 0328aa0630 Forwarded accept messages aren't visible to the introducee. 2021-04-13 08:46:00 -03:00
akwizgran b6cf302131 Only use conversation timestamp for messages that will be visible in conversation. 2021-04-13 08:46:00 -03:00
akwizgran e2a894acd3 Get timestamp for abort message in same way as other messages. 2021-04-13 08:45:59 -03:00
akwizgran 00ed6d9bb8 Look up auto-delete timer when creating private group invitation. 2021-04-13 08:45:59 -03:00
akwizgran c9a9734368 Use the right timestamp when signing private group invitation. 2021-04-13 08:45:58 -03:00
akwizgran efc56a8724 Provide TransactionManager. 2021-04-13 08:45:58 -03:00
akwizgran 6e6923b108 Look up conversation timestamp when creating group invitation messages. 2021-04-13 08:45:58 -03:00
akwizgran f459beccdb Move lookup of latest conversation timestamp to core for blog and forum sharing. 2021-04-13 08:45:57 -03:00
akwizgran 751c5a3245 Move lookup of latest conversation timestamp to core. 2021-04-13 08:45:57 -03:00
akwizgran 8488499da6 Add transactional variant of getGroupCount(). 2021-04-13 08:45:57 -03:00
akwizgran 96a7e3c425 Send current minor version of messaging client to contacts. 2021-04-13 08:45:56 -03:00
Torsten Grote 0dcf510466 Show bomb icon for messages with auto-destruct timer 2021-04-13 08:45:56 -03:00
akwizgran 0427b12d52 Check that timer argument is legal before storing. 2021-04-13 08:45:56 -03:00
akwizgran 9256c66fcc Add unit tests for AutoDeleteManagerImpl. 2021-04-13 08:45:55 -03:00
akwizgran 706f4e1c4c Implement AutoDeleteManager. 2021-04-13 08:45:55 -03:00
akwizgran 96debcd616 Add dummy implementation of AutoDeleteManager. 2021-04-13 08:45:54 -03:00
akwizgran 07f20e1e0d Refactor auto-delete code from Bramble to Briar. 2021-04-13 08:45:54 -03:00
akwizgran fee2e503bd Rewrap lines. 2021-04-13 08:45:54 -03:00
akwizgran f9f260bbc1 Factor out methods for storing and retrieving contact ID. 2021-04-13 08:45:53 -03:00
akwizgran 61718192ee Factor out method for validating auto-delete timers. 2021-04-13 08:45:53 -03:00
akwizgran 27893f9cdd Update comments. 2021-04-13 08:45:53 -03:00
akwizgran 9b0b80ef04 Add unit tests for validating auto-delete timer. 2021-04-13 08:45:52 -03:00
akwizgran 3e1c2df4b1 Update private group invitation client to include self-destruct timers. 2021-04-13 08:45:52 -03:00
akwizgran fa745410cc Update blog and forum sharing clients to include self-destruct timers. 2021-04-13 08:45:51 -03:00
akwizgran a427624e8d Update message parsing and encoding to include auto-delete timer. 2021-04-13 08:45:51 -03:00
akwizgran 3798ca1e17 Update introduction validator to support auto-delete timers. 2021-04-13 08:45:51 -03:00
akwizgran 113120b3ab Add constant for NO_AUTO_DELETE_TIMER, address review comments. 2021-04-13 08:45:50 -03:00
akwizgran b10ca5b77f Add unit tests for private message validation. 2021-04-13 08:45:50 -03:00
akwizgran f10e3d756a Fix comments in PrivateMessageValidator. 2021-04-13 08:45:50 -03:00
akwizgran 9608b974ec Add integration test for auto-delete timer in private messages. 2021-04-13 08:45:49 -03:00
akwizgran 3b6cc9c633 Add auto-deletion timer to private messages. 2021-04-13 08:45:47 -03:00
akwizgran 5305dd62d1 Merge branch '1872-key-agreement' into 'master'
Finish migrating KeyAgreementActivity to ViewModel

Closes #1982 and #1872

See merge request briar/briar!1357
2021-04-12 13:19:51 +00:00
akwizgran a066190c60 Merge branch '57-detect-db-durability-failures' into 'master'
Implement dirty flag to detect durability failures

Closes #57

See merge request briar/briar!1424
2021-04-12 13:17:28 +00:00
akwizgran cdae8b35f5 Another small refactoring to make control flow easier to understand. 2021-04-12 10:06:49 -03:00
Torsten Grote 6ee57315dd Prevent NPE when onQrCodeDecoded() is called after we stop to listen 2021-04-12 10:06:48 -03:00
Sebastian Kürten 64f682146d Integrate merge request feedback 2021-04-12 13:04:42 +02:00
akwizgran 36525fbe9d Merge branch 'promo-video' into 'master'
Instrumentation test for tutorial video and sign-in

Closes #1967

See merge request briar/briar!1423
2021-04-12 10:46:03 +00:00
Torsten Grote 8f628f2d45 Fix PromoVideoTest for CI 2021-04-09 15:24:13 -03:00
Torsten Grote 5e84e5b8b6 Stop listening to key agreement connections when leaving fragment
Also don't liberate screen orientation when backing out of adding a contact nearby
2021-04-09 15:20:39 -03:00
Torsten Grote a64878bd00 Also reset payload flags when resetting AddNearbyContact state 2021-04-08 14:21:17 -03:00
Torsten Grote c53fc5eaa3 Add inspection profile to repo
so we can all share the same inspection profile and benefit from its warnings
2021-04-08 13:55:26 -03:00
akwizgran 212751c835 Return a value instead of passing a runnable argument. 2021-04-08 17:11:07 +01:00
akwizgran fe1c6acebb Remove workaround for Android issue #190966. 2021-04-08 17:03:28 +01:00
Sebastian Kürten ce47bfe018 Write tests for the dirty flag 2021-04-08 12:24:23 +02:00
Torsten Grote 0ee4ade404 One more round of addressing AddNearbyContact review feedback 2021-04-07 16:18:18 -03:00
Sebastian Kürten e99df2b69e Log dirty flag when opening database 2021-04-06 20:19:28 +02:00
Sebastian Kürten db84d07c38 Store a dirty flag in the database 2021-04-06 19:45:26 +02:00
Torsten Grote db610cfb4c Run only tests from android package on emulator
Otherwise, it re-runs bramble tests for some reason
2021-04-01 17:12:04 -03:00
Torsten Grote 5b52417d20 Check if Bluetooth is supported before requesting discoverability 2021-04-01 15:36:55 -03:00
Torsten Grote 8a768cf933 Add a test for sign-in
This requires an account to exist before as we can't restart our lifecycle.
So we don't automatically clear app data after each test, but rather need to delete an existing account manually before each test.
2021-04-01 14:31:34 -03:00
akwizgran bebf3bbc39 Merge branch '1826-settings-view-model' into 'master'
Finish migrating SettingsFragment to ViewModel

Closes #1942 and #1826

See merge request briar/briar!1350
2021-04-01 13:20:12 +00:00
Torsten Grote 8a3dd5472b Make a screenshot when test fails to help with debugging 2021-03-31 13:36:55 -03:00
Torsten Grote f971533a5b Add a way to detect if code runs as instrumentation test
and disable some dialogs to make tests easier to write
2021-03-31 13:36:55 -03:00
Torsten Grote a12166c13b Use Android Test Orchestrator to have a clean state for each test
fixes flaky/broken espresso tests
2021-03-31 13:36:54 -03:00
Torsten Grote 51624a31e3 Add a first PromoVideoTest 2021-03-31 13:36:54 -03:00
Torsten Grote cdc632e1af Don't show screen filter and expiry warnings in screenshot tests 2021-03-30 16:56:03 -03:00
Torsten Grote 31f87f647e Create an OverlayView so we can show taps in espresso tests 2021-03-30 16:56:03 -03:00
Torsten Grote dcd37f71d1 Turn splash screen duration into a resource variable
so screenshot tests can define a different duration
2021-03-30 16:56:03 -03:00
Torsten Grote 4ca286b28e Allow to decide whether test contacts should have alias 2021-03-30 16:56:02 -03:00
Torsten Grote 4f3e4b019a Request user to turn on location for adding contact nearby on API 28+ 2021-03-29 11:30:17 -03:00
akwizgran 62cca1335f Bump version numbers for 1.2.20 release. 2021-03-29 13:33:12 +01:00
akwizgran 11a18859fb Update translations. 2021-03-29 13:33:12 +01:00
akwizgran 1116a7e125 Merge branch 'update-bridges-again' into 'master'
Remove a failing bridge

See merge request briar/briar!1422
2021-03-29 12:32:11 +00:00
akwizgran 415b315292 Add a Tor Browser default bridge. 2021-03-29 13:01:27 +01:00
akwizgran 9818ec2b66 Remove a failing bridge. 2021-03-29 12:55:04 +01:00
Torsten Grote 95ef061a34 Pick up screen lock changes when returning to SecurityFragment 2021-03-26 14:33:58 -03:00
Torsten Grote aaaf8aa66f Go back to security settings when pressing navigation icon in ChangePasswordActivity 2021-03-26 14:12:02 -03:00
Torsten Grote 29965e38d0 Don't show Toast off the UiThread 2021-03-26 14:10:37 -03:00
Torsten Grote 371d49a213 Use SwitchPreferenceCompat for panic preferences
Addresses #1991
2021-03-26 14:10:36 -03:00
Torsten Grote 6ed95e145e Re-open DisplayFragment after changing theme 2021-03-26 13:48:20 -03:00
Torsten Grote 8c025c1173 review: fix nullability and visibility of settings 2021-03-26 13:48:19 -03:00
Torsten Grote 9ce541cc31 Allow settings titles on more than a single line 2021-03-26 13:48:19 -03:00
Torsten Grote aa57a4c123 lint ignore icon tinting since it seems to work on Android 4 with VectorDrawableCompat 2021-03-26 13:48:18 -03:00
Torsten Grote 58d9deb3b8 Move avatar layout into own preference
which is only shown on main settings fragment
2021-03-26 13:48:18 -03:00
Torsten Grote f0685c4a43 Get rid of custom switch preference 2021-03-26 13:48:18 -03:00
Torsten Grote 484817db08 Move notifications settings into own screen 2021-03-26 13:48:17 -03:00
Torsten Grote 670bf15d31 Move security settings into own screen 2021-03-26 13:48:17 -03:00
Torsten Grote 6df1e0fd77 Move connections settings into own screen 2021-03-26 13:48:17 -03:00
Torsten Grote ec910cb80f Move Display category into its own settings screen 2021-03-26 13:48:16 -03:00
akwizgran 372516646d Merge branch '1970-blog-bugs' into 'master'
Fix issues with blogs after refactoring

See merge request briar/briar!1421
2021-03-26 14:32:11 +00:00
Torsten Grote 72e721b0d3 Don't show snackbar about local blog post again after screen rotation 2021-03-26 10:56:57 -03:00
Torsten Grote 6599093611 Improve blog author clickability
resolves issue where clicking reblogged author opened reblogging author's blog
2021-03-26 10:40:51 -03:00
Torsten Grote dceeecf1fe Open blog posts from blog feed in BlogActivity 2021-03-26 10:23:31 -03:00
Torsten Grote ace0b9a3d8 Merge branch 'update-bridges' into 'master'
Replace a failing bridge with a Tor Browser default bridge

See merge request briar/briar!1420
2021-03-26 11:59:03 +00:00
akwizgran 7c45c90de9 Replace a failing bridge with a Tor Browser default bridge. 2021-03-26 09:27:36 +00:00
akwizgran c2a4b5e26a Bump version numbers for 1.2.19 release. 2021-03-25 17:36:04 +00:00
akwizgran feac0ad802 Update translations. 2021-03-25 17:34:02 +00:00
akwizgran 60478eba3f Merge branch '1866-blog-controller' into 'master'
Migrate BlogController and FeedController to ViewModel

Closes #1891 and #1866

See merge request briar/briar!1342
2021-03-25 17:25:43 +00:00
akwizgran 3639952612 Merge branch 'espresso-ci' into 'master'
Run instrumentation tests in CI when briar-android changes

Closes admin#20

See merge request briar/briar!1413
2021-03-25 15:47:18 +00:00
akwizgran c4a654b267 Merge branch '1979-feedback-crash' into 'master'
Don't crash when pressing SHOW with user information when sending feedback

Closes #1979

See merge request briar/briar!1418
2021-03-25 13:29:43 +00:00
Torsten Grote ecb31a4d32 Don't crash when pressing SHOW with user information when sending feedback 2021-03-25 08:47:18 -03:00
Torsten Grote 76f201bb2f Run Espresso tests manually as they are still too flaky 2021-03-24 16:10:33 -03:00
Torsten Grote 1d44305e34 Catch exception when calling Camera#getParameters()
Fixes #1982
2021-03-24 15:23:16 -03:00
Torsten Grote a37af592cd Use new ActivityResultLauncher to request permissions for AddNearbyContact 2021-03-24 15:03:53 -03:00
akwizgran 87799b743c Add Burmese translation to language chooser. 2021-03-24 15:28:33 +00:00
akwizgran b898a7c370 Update translations, add Burmese translation. 2021-03-24 13:54:00 +00:00
Torsten Grote 7f486eef4c Refactor more code into AddNearbyContactViewModel
thus concentrating the logic there needing less back and forth with the activity
2021-03-23 18:09:57 -03:00
Torsten Grote f3210e3af2 Allow DbViewModel work on things other than lists. 2021-03-23 12:59:16 -03:00
akwizgran 225fd6fd49 Merge branch 'headless-remove-type-args-in-jar-sorting-algorithm' into 'master'
Remove redundant type args in briar-headless/build.gradle

See merge request briar/briar!1416
2021-03-23 12:38:53 +00:00
Sebastian Kürten 400d259a60 Remove redundant type args in briar-headless/build.gradle
The TreeMap<> doesn't need to repeat <String, JarEntry> from
Map<String, JarEntry>.
2021-03-23 07:44:02 +01:00
Torsten Grote 4074ac8578 Add handleException() to DbViewModel
and use it for blogs
2021-03-22 15:17:30 -03:00
Torsten Grote b2e6dd4138 publish log files as artifacts when emulator job fails 2021-03-19 14:19:07 -03:00
Torsten Grote b608b42174 Run instrumentation tests in CI when briar-android changes 2021-03-18 12:15:47 -03:00
Torsten Grote f603254153 Fix instrumentation tests 2021-03-18 12:15:46 -03:00
Torsten Grote c851dd228b Add a different (faster) way to exclude large/slow tests 2021-03-18 12:15:46 -03:00
Torsten Grote e97478a21a Don't reload blog data when configuration changes 2021-03-17 14:16:02 -03:00
Torsten Grote 726ebcea3f Make blog post author clickable when not already in their blog 2021-03-17 14:16:02 -03:00
Torsten Grote 2f969775d8 Remove TransactionManager from blog's BaseViewModel 2021-03-17 14:16:02 -03:00
Torsten Grote d3b855318c Anticipate review feedback for blog view models after re-basing 2021-03-17 14:16:01 -03:00
Torsten Grote 95104d3383 Clean up after migrating blog controllers to view model 2021-03-17 14:16:01 -03:00
Torsten Grote 6860a04e8b Don't use layoutManager hack to restore scrolling position of blogs
not needed anymore when posts are cached in viewmodels
2021-03-17 14:16:01 -03:00
Torsten Grote 33c24f8655 Migrate blogs to new SharingController
and get rid of the deprecated one
2021-03-17 14:16:00 -03:00
Torsten Grote 1fa4b78474 Migrate BlogController to BlogViewModel 2021-03-17 14:16:00 -03:00
Torsten Grote b678de7529 Make BlogAdapter final and don't pass in a FragmentManager 2021-03-17 14:16:00 -03:00
Torsten Grote ab1ed0ff5a Turn FeedController into FeedViewModel 2021-03-17 14:15:59 -03:00
Torsten Grote ad20e5230a Allow blog posts to be loaded within one transaction 2021-03-17 14:15:59 -03:00
Torsten Grote bcc0442add Merge activities for adding contact nearby
and rename related classes to consolidate names
2021-03-17 14:05:15 -03:00
Torsten Grote 700f6e05bf Factor out permission related code from KeyAgreementActivity to AddNearbyContactPermissionManager 2021-03-17 14:02:54 -03:00
Torsten Grote d8327d6de2 Re-set orientation lock when fragment is left 2021-03-17 14:02:54 -03:00
Torsten Grote 5a55b3d7e3 Move Plugin related code from activity to ViewModel 2021-03-17 14:02:54 -03:00
Torsten Grote bed87ed439 Move backend comms and logic out of KeyAgreementFragment
into ViewModel
2021-03-17 14:02:53 -03:00
Torsten Grote 6d1f1c7852 Get rid of KeyAgreementEventListener
and communicate via ViewModel
2021-03-17 14:02:53 -03:00
Torsten Grote f6b3bde724 Introduce ContactExchangeResult
to include all result information in LiveData
2021-03-17 14:02:53 -03:00
Torsten Grote 94ec22bef8 Move keyagreement package into contact.add.nearby
and fix some small warnings in the process
2021-03-17 14:02:50 -03:00
Torsten Grote ae923e5777 Merge branch '1871-viewmodel-for-introduction' into 'master'
Introduce ViewModel for IntroductionActivity (and ContactChooserFragment)

See merge request briar/briar!1349
2021-03-16 18:46:45 +00:00
Sebastian Kürten 46b4204805 Introduce view model for IntroductionActivity 2021-03-16 19:34:09 +01:00
akwizgran 2257c005b3 Merge branch 'faster-animations' into 'master'
Use a central attribute for animation speed

See merge request briar/briar!1368
2021-03-15 15:57:26 +00:00
Torsten Grote eb9ff9c954 Use a central attribute for animation speed 2021-03-15 12:02:43 -03:00
Torsten Grote 4f08f81779 Merge branch 'raise-max-mime-type-length' into 'master'
Test that a max-length attachment fits into a record.

See merge request briar/briar!1411
2021-03-15 13:37:12 +00:00
akwizgran 2b0815aaac Merge branch '1951-exclude-files-from-backup' into 'master'
Exclude all our files from backup

Closes #1951

See merge request briar/briar!1408
2021-03-15 13:25:52 +00:00
akwizgran a9e83491d3 Test that a max-length attachment fits into a record. 2021-03-15 13:17:07 +00:00
Torsten Grote ee967c5d8f Merge branch 'raise-max-mime-type-length' into 'master'
Raise MAX_CONTENT_TYPE_BYTES to 80, lower MAX_PRIVATE_MESSAGE_TEXT_LENGTH

See merge request briar/briar!1409
2021-03-15 13:06:24 +00:00
akwizgran 43740777d4 Raise MAX_CONTENT_TYPE_BYTES to 80, lower MAX_PRIVATE_MESSAGE_TEXT_LENGTH.
In case we ever want to send "application/vnd.openxmlformats-officedocument.wordprocessingml.document" attachments.
2021-03-12 09:45:19 +00:00
Torsten Grote d5b0556ea2 Exclude all our files from backup
Even though we don't allow backup at all, Android seems to go into the direction of overriding this. For now only for device-to-device backups, even though we could not verify this.
2021-03-11 16:29:44 -03:00
Torsten Grote 227f00c10c Merge branch '1899-catch-npe-from-bluetooth-socket' into 'master'
Catch NPE from BluetoothSocket#connect()

Closes #1899

See merge request briar/briar!1407
2021-03-11 18:09:59 +00:00
akwizgran 8b4ff2dc8a Catch NPE from BluetoothSocket#connect(). 2021-03-11 18:00:45 +00:00
akwizgran 4be2afb915 Merge branch 'do-not-try-to-load-unsupported-content-types' into 'master'
Don't try to load attachments with unsupported content types

See merge request briar/briar!1405
2021-03-11 17:48:55 +00:00
Torsten Grote 74447b8ec3 Merge branch 'allow-gifs' into 'master'
Allow GIFs to be chosen on all API levels

See merge request briar/briar!1402
2021-03-11 17:25:50 +00:00
akwizgran d95242bd7e Don't try to load attachments with unsupported content types. 2021-03-11 16:59:56 +00:00
akwizgran 51794424ce Bump version numbers for 1.2.18 release. 2021-03-11 15:25:32 +00:00
Torsten Grote 5db099bae6 Merge branch 'update-bridges' into 'master'
Update list of Tor bridges

See merge request briar/briar!1403
2021-03-11 15:20:11 +00:00
Torsten Grote a2faa3bd3b Merge branch '1612-do-not-strip-libs' into 'master'
Don't strip libraries even if the NDK is installed

See merge request briar/briar!1401
2021-03-11 15:14:20 +00:00
akwizgran a3fb7b5680 Update list of Tor bridges. 2021-03-11 14:24:46 +00:00
akwizgran 264d110dbd Bump version numbers for 1.2.17 release. 2021-03-11 12:35:19 +00:00
akwizgran 839b871a45 Merge branch 'aarch64-finalization' into 'master'
Make headless work on aarch64 and armhf (armv7)

Closes #1854

See merge request briar/briar!1376
2021-03-11 12:28:55 +00:00
akwizgran 2fb4825b8f Don't strip libraries even if the NDK is installed.
This allows reproducible builds regardless of whether the NDK is installed.
2021-03-11 12:20:41 +00:00
Torsten Grote 3f9a66b1b6 Merge branch '1964-no-colons' into 'master'
Remove colons from default filename

Closes #1964

See merge request briar/briar!1400
2021-03-11 11:36:49 +00:00
akwizgran d796916387 Also remove colons on API >= 19. 2021-03-11 10:33:53 +00:00
akwizgran fe07b760ea Remove colons from default filename. 2021-03-10 15:44:15 +00:00
akwizgran b4a5fe6772 Allow GIFs to be chosen on API < 24.
We can compress them without resizing.
2021-03-10 15:42:20 +00:00
Nico Alt e21e6267d7 Update Tor dependency to include armhf binary
Related MR:
https://code.briarproject.org/briar/tor-reproducer/-/merge_requests/13
2021-03-09 10:46:43 +01:00
Nico Alt d7afbdf690 Use Tor binary for armhf (armv7)
Example devices are Nexus 5 and Raspberry Pi v2.

Based on https://code.briarproject.org/briar/briar/-/merge_requests/1376

Related to https://code.briarproject.org/briar/briar/-/issues/1854
2021-03-09 12:00:00 +00:00
Torsten Grote c5d2661c1d Merge branch '1919-password-fields-not-focusable' into 'master'
Condition display of progressbar on a isCreatingAccount LiveData

Closes #1819 and #1919

See merge request briar/briar!1355
2021-03-03 13:10:29 +00:00
Nico Alt b738bdd14e Actually make headless work on arm aarch64
Following the two comments at
https://code.briarproject.org/briar/briar/-/issues/1854#note_44340

.jar files now get built with

    $ ./gradlew --configure-on-demand briar-headless:x86LinuxJar
    $ ./gradlew --configure-on-demand briar-headless:aarch64LinuxJar

Related to #1854
2021-03-03 12:00:00 +00:00
akwizgran 629cff20a3 Merge branch '1952-oom-avatar-preview-glide' into 'master'
Load avatar previews with Glide to prevent OOM errors

Closes #1952

See merge request briar/briar!1388
2021-03-01 18:02:19 +00:00
Torsten Grote 6cfb70db95 Load image from URI with Glide to prevent OOM errors 2021-03-01 14:15:53 -03:00
Torsten Grote 737ecfb620 Some unrelated code changes to avatar settings 2021-03-01 14:15:08 -03:00
akwizgran 5a424b178e Merge branch '1667-toolbar-options' into 'master'
Make group/create forum/write blog post buttons to always show

Closes #1667

See merge request briar/briar!1377
2021-03-01 16:34:14 +00:00
Torsten Grote 59f4e7c34a Super call to onRequestPermissionsResult() is now required 2021-02-23 10:55:20 -03:00
Torsten Grote 2480824d69 Fix toolbar buttons not showing up after sign-in on lower API levels 2021-02-23 10:55:20 -03:00
akwizgran a6c2000d81 Merge branch '1825-pending-contact-error' into 'master'
Be more specific about errors when adding pending contact

Closes #1825

See merge request briar/briar!1354
2021-02-22 11:12:49 +00:00
akwizgran a38a3139d9 Merge branch 'fix-message-in-profile-picture-confirmation' into 'master'
Fix message in profile picture confirmation

See merge request briar/briar!1356
2021-02-22 11:06:58 +00:00
akwizgran 4c8adaa02b Merge branch '1399-unlock-activity-crash' into 'master'
Let LockManager only lock current, not future process

Closes #1399

See merge request briar/briar!1374
2021-02-22 10:49:17 +00:00
akwizgran 8a534b4503 Bump version numbers for 1.2.16 release. 2021-02-19 18:01:56 +00:00
akwizgran e5b2275c82 Merge branch '1947-forum-crash' into 'master'
Don't add new thread items when the existing ones haven't loaded

Closes #1947

See merge request briar/briar!1375
2021-02-19 17:27:38 +00:00
Torsten Grote 5159593825 Don't add new item when the existing ones haven't loaded 2021-02-19 14:17:21 -03:00
Torsten Grote a546fecc01 Let LockManager only lock current, not future process
This fixes a bug on Android 8
where the AlarmManager would re-start a killed BriarService.
Then the LockManager lingers around locked and causes an ANR on Android 8.x when the user comes back to it.
2021-02-19 10:42:43 -03:00
Nico Alt 3e7e37f5f6 Include pending contact id in error response 2021-02-19 12:00:00 +00:00
Nico Alt d095ba0b15 Include name/alias of already existing (pending) contact in error 2021-02-19 14:44:56 +01:00
Nico Alt 7fab97d26c Be more specific about errors when adding pending contact
Following the docs at
https://code.briarproject.org/briar/briar/-/blob/beta-1.2.14/bramble-api/src/main/java/org/briarproject/bramble/api/contact/ContactManager.java#L110

Fixes #1825
2021-02-19 14:44:56 +01:00
akwizgran 6fbc82ee27 Merge branch '1075-1146-1317-ongoing-notification' into 'master'
Use IMPORTANCE_LOW for ongoing notification, don't show a badge

Closes #1317, #1146, and #1075

See merge request briar/briar!1369
2021-02-18 17:00:47 +00:00
akwizgran 885b03cfd7 Bump version numbers for 1.2.15 release. 2021-02-18 15:27:57 +00:00
akwizgran f81bfcafeb Update translations. 2021-02-18 15:26:10 +00:00
akwizgran f36f1cf3d4 Merge branch '1764-fix-change-app-language-does-not-work' into 'master'
Resolve "Change app language does not work"

Closes #1764

See merge request briar/briar!1367
2021-02-17 16:59:59 +00:00
Torsten Grote 7d6a63d866 Merge branch '1934-upgrade-obfs4proxy' into 'master'
Upgrade obfs4proxy to 0.0.12-dev

Closes #1934

See merge request briar/briar!1372
2021-02-17 16:58:22 +00:00
akwizgran 15ebdf8dd5 Upgrade obfs4proxy to 0.0.12-dev. 2021-02-17 16:41:49 +00:00
akwizgran db2c235283 Merge branch 'private-group-disabled' into 'master'
Fix disabled groups after screen rotation

See merge request briar/briar!1371
2021-02-17 14:09:57 +00:00
Daniel Lublin 6b61725c6a Condition display of progressbar on a isCreatingAccount LiveData
Avoiding the mess with saving onSaveInstanceState, and the (in this
case) unwanted restoring of it upon back-button tap.

Closes #1919

Test instructions:

- Precondition: fresh install, setting up a new account
  - Testing specific bug fix:
    - Choose a name, tap next
    - Choose a password, tap next
      - Not testable on some devices which display "Create account" instead of "Next"
    - You are now on Background connections screen
    - Tap Back-button ◁
    - Ensure that password can be changed again
  - During setup process, rotate device and ensure that:
    - entered text is kept
    - progressbar is continuously displayed
2021-02-17 13:57:08 +01:00
Sebastian Kürten e5bd43469e Add Javados to Localizer#setLocale() 2021-02-15 14:54:20 +01:00
Torsten Grote 9366c184d8 Fix disabled groups after screen rotation
isDissolved was reverted to LiveData that only shows a dialog when the activity was first opened
2021-02-15 09:55:59 -03:00
Sebastian Kürten 73d2c964d4 Make language switching for robust 2021-02-15 12:31:51 +01:00
akwizgran fb2b4209cf Use IMPORTANCE_LOW for ongoing notification, don't show a badge. 2021-02-10 11:46:41 +00:00
Torsten Grote a04b512497 Merge branch 'tor-0.3.5.13' into 'master'
Upgrade Tor to 0.3.5.13

Closes #1922

See merge request briar/briar!1363
2021-02-09 12:15:45 +00:00
akwizgran 3d9515e308 Also upgrade obfs4proxy and bramble-java's Tor. 2021-02-09 12:05:54 +00:00
akwizgran 1b19b331b1 Merge branch '1904-fragment-started-too-late' into 'master'
Don't launch fragments with back button when not started

Closes #1904

See merge request briar/briar!1365
2021-02-09 11:05:08 +00:00
akwizgran d151a2d7f7 Merge branch '1910-state-exception-when-adding-contact' into 'master'
Restore remote handshake link when AddContactViewModel gets destroyed

Closes #1910

See merge request briar/briar!1364
2021-02-09 10:49:38 +00:00
Torsten Grote 9712a4b849 Don't launch fragments with back button when not started
Sounds strange, but apparently can happen.
2021-02-08 16:38:15 -03:00
Torsten Grote cf1ac5e3e5 Restore remote handshake link when AddContactViewModel gets destroyed 2021-02-08 16:03:10 -03:00
Torsten Grote cb859e998d Upgrade Tor to 0.3.5.13 2021-02-08 15:44:35 -03:00
akwizgran 0b9345f867 Merge branch '1621-link-disappearing' into 'master'
Remove monospace typeface from our briar:// link

Closes #1621

See merge request briar/briar!1362
2021-02-08 18:36:16 +00:00
Torsten Grote 12988120d1 Remove monospace typeface from our briar:// link
as this makes the text to become invisible when selecting all text on API 15-17
2021-02-08 14:45:57 -03:00
akwizgran 8d6c866e62 Merge branch '1926-cap-scrypt-cost' into 'master'
Cap the scrypt cost parameter to avoid OOM

Closes #1926

See merge request briar/briar!1360
2021-02-08 17:30:57 +00:00
akwizgran 8f82cf3c73 Merge branch '1917-logcat-process' into 'master'
Fix crash reporter to capture logs from main process

Closes #1917

See merge request briar/briar!1359
2021-02-08 16:58:12 +00:00
Torsten Grote 21112ce092 Encrypt logs before handing them to crash report process 2021-02-08 13:43:37 -03:00
akwizgran 21ee3ea00d Merge branch 'add-custom-dictionary' into 'master'
Add a custom dictionary

See merge request briar/briar!1361
2021-02-08 14:01:43 +00:00
Sebastian Kürten bb964101b3 Add a custom dictionary
This reduces the amount of words highlighted by the spell checker and
helps focussing on words that are really misspelled.
2021-02-08 14:35:14 +01:00
akwizgran d796eff0f6 Cap the scrypt cost parameter to avoid OOM. 2021-02-08 11:32:03 +00:00
Torsten Grote 700ea2b387 Add support for logs to StreamReader and StreamWriter
Shamelessly stolen from d9b4c013
2021-02-05 17:07:48 -03:00
Sebastian Kürten e4a66615a7 Fix remark in dialog for confirming profile picture 2021-02-04 18:43:32 +01:00
Torsten Grote 6e3a7d8d0c Merge branch 'gitlab-bridge-test' into 'master'
Add GitLab pipeline stage for running optional tests

See merge request briar/briar!1353
2021-01-29 16:07:49 +00:00
akwizgran 166b5d4add Run optional tests automatically for tags, otherwise manually. 2021-01-29 15:45:39 +00:00
akwizgran 0fd59a26f6 Raise BridgeTest timeout to avoid spurious failures. 2021-01-29 15:39:59 +00:00
akwizgran 4162bf990a Merge branch '1881-thread-list-controller' into 'master'
Migrate ThreadListController to ViewModel

Closes #1881, #1873, and #1870

See merge request briar/briar!1336
2021-01-29 15:10:16 +00:00
akwizgran 09cfadbf7e Add manual pipeline stage for running optional tests. 2021-01-29 14:38:03 +00:00
akwizgran 3fb27dbb12 Bump version numbers for 1.2.14 release. 2021-01-29 14:10:24 +00:00
Torsten Grote ae4a04bada Finishing touches of ThreadListViewModel migration
docs and minor improvements
2021-01-29 08:33:28 -03:00
akwizgran 831c65b647 Merge branch 'vector-compat' into 'master'
Use vector support libraries instead of rasterizing all drawables

See merge request briar/briar!1346
2021-01-28 17:59:08 +00:00
akwizgran afcd38b84c Update translations. 2021-01-28 16:15:44 +00:00
Torsten Grote d670179e30 Access MessageTree only on UiThread and improve code in the process 2021-01-27 15:37:09 -03:00
Torsten Grote 998c435b13 Allow to add forum/group posts in transaction 2021-01-27 15:37:09 -03:00
Torsten Grote 4a0327a62b thread list: fix redundant load and dissolved dialog showing again after screen rotation 2021-01-27 15:37:08 -03:00
akwizgran 70532732c8 Use commit action to add contacts on UI thread. 2021-01-27 15:37:08 -03:00
akwizgran d69406dfe3 Add transactional getSharedWith() method to SharingManager. 2021-01-27 15:37:08 -03:00
akwizgran 98619df867 Use commit action to add contacts to SharingController. 2021-01-27 15:37:07 -03:00
akwizgran f2eca0fdb6 Add transactional getMembers() method to PrivateGroupManager. 2021-01-27 15:37:07 -03:00
akwizgran c62a57e8b2 Add transactional helper method to DbViewModel. 2021-01-27 15:37:07 -03:00
Torsten Grote 239c4a27ad Address first round of review feedback for thread list view model migration 2021-01-27 15:37:06 -03:00
Torsten Grote e5d78a858d Clear thread notification automatically after blocking new ones 2021-01-26 15:42:18 -03:00
Torsten Grote 5c1bcdeb9d Merge branch 'update-bridges' into 'master'
Update bridges

See merge request briar/briar!1352
2021-01-26 14:11:00 +00:00
akwizgran 6c1f5450cb Add run configuration for BridgeTest. 2021-01-26 13:57:33 +00:00
akwizgran 0d070cf422 Change dummy address for meek bridge.
See https://gitweb.torproject.org/builders/tor-browser-build.git/commit/projects/tor-browser/Bundle-Data/PTConfigs/bridge_prefs.js?id=8bd845464ae14bf56e0187dfa6f6e773a6593f55
2021-01-26 13:53:51 +00:00
akwizgran d34d66c691 Update list of obfs4 bridges. 2021-01-26 13:51:41 +00:00
Torsten Grote 6005d156eb Rename ic_lock icon to notification_lock 2021-01-26 08:24:16 -03:00
Torsten Grote 635008fb60 Introduce SharingController with LiveData
and get rid of ThreadList controllers
2021-01-25 14:04:29 -03:00
Torsten Grote b78569119a Remove Visibility from JoinMessageHeader and Item 2021-01-25 14:04:28 -03:00
Torsten Grote 8372bb01b2 Move marking thread list items read to ViewModel 2021-01-25 14:04:28 -03:00
Torsten Grote 766718e75c Remove text cache as it is no longer needed 2021-01-25 14:04:28 -03:00
Torsten Grote 1c107a851b Move thread list events, fields and notification handling into ViewModels 2021-01-25 14:04:26 -03:00
Torsten Grote db53e79d1d Remove ForumActivityTest which provided little value anyway 2021-01-25 14:04:17 -03:00
Torsten Grote 21e56284fb Move adding new ThreadList items to ViewModel 2021-01-25 14:04:16 -03:00
Torsten Grote d393b79ced Submit thread list items to ListAdapter 2021-01-25 14:04:09 -03:00
Torsten Grote 6611d7c02e Move removal of named groups into ViewModel 2021-01-25 14:00:43 -03:00
Torsten Grote ab43dd4986 Create ThreadListViewModels and move loading of named groups there 2021-01-25 14:00:41 -03:00
Torsten Grote 36a9174781 Perform thread list core access within a single transaction 2021-01-25 14:00:15 -03:00
Torsten Grote 94dd75f24b Use VectorDrawableCompat compatible ways of setting drawables programmatically
so they won't crash on API < 21
2021-01-25 13:34:27 -03:00
Torsten Grote c93e5441b0 Store rasterized notification icons, because NotificationCompat doesn't handle it
and would crash on API < 21
2021-01-25 13:34:27 -03:00
Torsten Grote 8ec8cc927b Use vector support libraries instead of rasterizing all drawables
https://developer.android.com/guide/topics/graphics/vector-drawable-resources#vector-drawables-backward-solution
2021-01-25 13:34:26 -03:00
akwizgran 4663e727eb Merge branch '214-user-avatars' into 'master'
Merge user avatars feature branch

See merge request briar/briar!1334
2021-01-25 15:15:54 +00:00
akwizgran e2acd19ffd Trivial code cleanups. 2021-01-25 15:05:15 +00:00
akwizgran 0befa6a823 Use NullSafety.equals(). 2021-01-25 15:05:15 +00:00
Torsten Grote 01083f47ea Merge branch '1865-setupcontroller-to-viewmodel' into 'master'
Migrate SetupController to a ViewModel

See merge request briar/briar!1340
2021-01-25 14:03:32 +00:00
Daniel Lublin a349bd146c Migrate SetupController to a ViewModel
Solves #1865
2021-01-25 14:34:19 +01:00
Torsten Grote 4ffa9e191c Merge branch '1912-specify-group-id-when-loading-attachment' into '214-user-avatars'
Ensure that attachment has expected group ID when loading

See merge request briar/briar!1347
2021-01-25 12:58:19 +00:00
akwizgran e616fc3da7 Throw NoSuchMessageException if attachment is invalid. 2021-01-22 14:01:36 +00:00
akwizgran aed5ac5bb4 Ensure that attachment has expected group ID when loading. 2021-01-22 13:35:06 +00:00
Sebastian Kürten cae53a9fcc Reorganize MediaModule and AttachmentModule 2021-01-21 10:13:29 -03:00
Sebastian Kürten 6660625ba6 Update avatar in contact list when changed while list is open 2021-01-21 10:13:29 -03:00
Sebastian Kürten bf9ba13b68 Update app bar in ConversationActivity with received avatar 2021-01-21 09:33:56 -03:00
Sebastian Kürten a52c97ecf7 Format touched xml layouts 2021-01-21 09:33:56 -03:00
Sebastian Kürten a2174e7677 SettingsViewModel: use LiveEvent instead of LiveData 2021-01-21 09:33:55 -03:00
Sebastian Kürten d3cf3d680e Display error message toast when updating profile picture fails 2021-01-21 09:33:55 -03:00
Sebastian Kürten cbb87aa00c Move compression of image to IoExecutor 2021-01-21 09:33:55 -03:00
Sebastian Kürten 53d985161f Remove layout_gravity without any effect 2021-01-21 09:33:54 -03:00
Sebastian Kürten 86002b0402 Move some findViewById() out of a lambda 2021-01-21 09:33:54 -03:00
Sebastian Kürten f75e789493 Improve dialog for avatar confirmation 2021-01-21 09:33:54 -03:00
Sebastian Kürten b22f302fdd Statically import Level.WARNING 2021-01-21 09:33:53 -03:00
Sebastian Kürten c4a42760c8 Use BriarDialogTheme for avatar confirmation 2021-01-21 09:33:53 -03:00
Sebastian Kürten 8d92f36522 Remove some useless tools:text 2021-01-21 09:33:53 -03:00
Sebastian Kürten 6c86873ea7 Reduce margin verbosity in SettingsActivity 2021-01-21 09:33:52 -03:00
Sebastian Kürten 4fa9d654b5 Eliminate NestedScrollView from SettingsActivity 2021-01-21 09:33:52 -03:00
Sebastian Kürten 3d303ccad5 Natural order of views in SettingsActivity 2021-01-21 09:33:52 -03:00
Sebastian Kürten b0d99a9f33 Avoid staircase indent 2021-01-21 09:33:51 -03:00
Sebastian Kürten 1a5e789bec Call loadOwnIdentityInfo() in SettingsViewModel's constructor 2021-01-21 09:33:51 -03:00
Sebastian Kürten 97040c6299 Remove a useless method call 2021-01-21 09:33:51 -03:00
Sebastian Kürten 301085c685 Move findViewById() out of callback 2021-01-21 09:33:50 -03:00
Sebastian Kürten 946c79d918 Be consequent with AlertDialog.Builder method usage 2021-01-21 09:33:50 -03:00
Sebastian Kürten 20418cfc7f Rename inflater variable 2021-01-21 09:33:50 -03:00
Sebastian Kürten 7b09f0f98d Rename a string 2021-01-21 09:33:49 -03:00
Sebastian Kürten 97a7c8824b Replace usage of UnsupportedMimeTypeException from jsoup with own type 2021-01-21 09:33:49 -03:00
Sebastian Kürten 423684a14f Reduce visibility of SettingsViewModel 2021-01-21 09:33:48 -03:00
Sebastian Kürten 09d91b522f Fix a warning in SettingsActvitiy 2021-01-21 09:33:48 -03:00
Sebastian Kürten 64c0e9e9e4 Fix a few warnings in ConfirmAvatarDialogFragment 2021-01-21 09:33:48 -03:00
Sebastian Kürten 15021bffef Inline getAttachmentFileIntent() 2021-01-21 09:33:48 -03:00
Sebastian Kürten 43c6ae4258 Implement UI for setting profile pictures 2021-01-21 09:33:47 -03:00
Sebastian Kürten f819930570 Create ImageCompressor amd ImageCompressorImpl
* Methods from AttachmentCreationTask have been moved into them:
  * compressImage()
  * createBitmap()
* ImageCompressor is availabe via AttachmentModule
2021-01-21 09:33:47 -03:00
Torsten Grote aa00ba7220 test avatars: get rid of the 1% 2021-01-21 09:33:47 -03:00
Torsten Grote 19db58ee19 Allow the user to configure the percentage of test contacts with avatars 2021-01-21 09:33:46 -03:00
Torsten Grote 05f4d63356 Create test avatars when creating test contacts 2021-01-21 09:33:46 -03:00
Torsten Grote 6e5af2d3d3 Create TestAvatarCreator for use in debug builds only 2021-01-21 09:33:46 -03:00
Torsten Grote 00bf1eac0a Factor out MessageEncoder from AvatarManager 2021-01-21 09:33:45 -03:00
akwizgran 8a10f16861 Deliver test messages as though they arrived from contacts. 2021-01-21 09:33:45 -03:00
Torsten Grote 9bd7214d1d Make AuthorManager volatile as it is accessed from DbThread 2021-01-21 09:33:45 -03:00
Torsten Grote fce1247aa6 Add a shortcut for setting avatar with ContactItem 2021-01-21 09:33:44 -03:00
Torsten Grote 990f983ea9 Evict Glide memory cache in a low mem situation 2021-01-21 09:33:44 -03:00
Torsten Grote 6e57d7bb42 Show avatars for contacts outside AuthorView 2021-01-21 09:33:38 -03:00
Torsten Grote 1b0cb532de Show Avatars in AuthorView 2021-01-21 09:20:03 -03:00
Torsten Grote fe7121b4ec Turn AttachmentReader into a proper class
and inject it where needed
2021-01-21 09:20:02 -03:00
Torsten Grote 5aa041f9e1 Add AuthorManager#getMyAuthorInfo() without transaction
and add test for it
2021-01-21 09:20:02 -03:00
Torsten Grote 6939d8d230 Upgrade glide to latest stable version 2021-01-21 09:20:02 -03:00
Torsten Grote c3cea37641 Add AttachmentHeader to AuthorInfo
This way the UI can retrieve the author's avatar (if it exists).
2021-01-21 09:20:01 -03:00
Torsten Grote d0d2e0ed82 Centralize attachment loading in AttachmentReader
This is needed so Glide can load attachments from the DB by using the same AttachmentHeader class.
2021-01-21 09:20:01 -03:00
Torsten Grote cf8f5c989f Move AuthorInfo from bramble to briar 2021-01-21 09:20:01 -03:00
Torsten Grote 8b45e01c42 Split up AvatarManagerImplTests 2021-01-21 09:20:00 -03:00
Torsten Grote ec972e8a1d Handle concurrent updates of our avatar 2021-01-21 09:20:00 -03:00
Torsten Grote 100791c3f3 Don't accept incoming messages in our own avatar group 2021-01-21 09:19:59 -03:00
Torsten Grote 83ac866cc1 Implement AvatarManager with unit and integration tests 2021-01-21 09:19:59 -03:00
Torsten Grote ef9b22670d Factor our attachment classes and constants
because they will be used by more than one client
2021-01-21 09:19:59 -03:00
Torsten Grote 186ac30f37 Use metadata constants in TransportPropertyValidator 2021-01-21 09:19:56 -03:00
Torsten Grote 5aa24414c6 Merge branch '1867-viewmodel-for-contactlistfragment' into 'master'
Introduce ViewModel for ContactListFragment

Closes #1867

See merge request briar/briar!1341
2021-01-18 13:12:43 +00:00
Sebastian Kürten dd6d72ed30 Introduce ViewModel for ContactListFragment 2021-01-18 14:01:48 +01:00
akwizgran 4344be2ca0 Merge branch '1753-wake-lock' into 'master'
Only query for allowed packages in AndroidWakeLockManager

Closes #1753

See merge request briar/briar!1332
2021-01-12 11:21:19 +00:00
akwizgran 1e94af3ef3 Merge branch 'screenshots-api29' into 'master'
Fix screenshot instrumentation tests on API 29+

See merge request briar/briar!1333
2021-01-11 17:58:19 +00:00
Torsten Grote cb69340749 Merge branch 'move-version-numbers-back-to-modules' into 'master'
Move version constants back into modules so F-Droid can find them

See merge request briar/briar!1338
2021-01-11 16:58:24 +00:00
akwizgran f3d068414b Move version constants back into modules so F-Droid can find them.
This reverts commit de9c6d44, except that the version numbers have
increased in the meantime.
2021-01-11 16:46:41 +00:00
akwizgran 5fdc7e7cc4 Bump version numbers for 1.2.13 release. 2021-01-07 16:23:11 +00:00
akwizgran 7569d5ffb3 Update translations. 2021-01-07 16:21:59 +00:00
akwizgran deca5d56cc Merge branch '1885-malformed-links' into 'master'
Do not produce malformed links for adding contacts when on other locales such as Turkish

Closes #1885

See merge request briar/briar!1335
2021-01-07 15:07:55 +00:00
Torsten Grote 3d6b48bb34 Do not produce malformed links for adding contacts when on other locales
such as Turkish
2021-01-07 11:52:27 -03:00
akwizgran 0dc631b7a8 Merge branch '1869-forum-list-view-model' into 'master'
Introduce ViewModel for ForumListFragment

Closes #1869

See merge request briar/briar!1331
2021-01-07 14:45:47 +00:00
Torsten Grote 921e952b05 Rename ForumItem to ForumPostItem 2021-01-07 08:58:14 -03:00
Torsten Grote 3b02797639 Block forum post notifications while viewing forum list 2021-01-07 08:58:14 -03:00
Torsten Grote e2e67edbbe Introduce ForumListViewModel 2021-01-07 08:58:13 -03:00
Torsten Grote a9cd40faeb Add transactions to methods in ForumManager 2021-01-07 08:58:13 -03:00
Torsten Grote dd3c19aba2 Fix screenshot instrumentation tests on API 29+ 2021-01-05 14:40:25 -03:00
Torsten Grote e8ede55422 Only query for allowed packages in AndroidWakeLockManager 2021-01-05 14:11:00 -03:00
akwizgran 04517e942e Merge branch '1753-query-filter' into 'master'
Define manifest <queries> allowing us to make intent queries on API 30+

See merge request briar/briar!1323
2021-01-05 14:47:00 +00:00
akwizgran 9a25ad892d Merge branch '1753-screen-filter' into 'master'
Prepare screen overlay warning for targeting API 30

See merge request briar/briar!1322
2021-01-05 14:31:10 +00:00
akwizgran 3457d8f9ab Merge branch '1861-no-wifi-networks' into 'master'
Remove calls to WifiManager#getConfiguredNetworks()

Closes #1861

See merge request briar/briar!1330
2021-01-05 14:03:40 +00:00
Torsten Grote 5fb2624ffa Remove calls to WifiManager#getConfiguredNetworks()
as these require fine location permission now and don't work when
location services are disabled.
2021-01-05 10:22:32 -03:00
akwizgran ed9a7bec2c Merge branch '1800-group-list-view-model' into 'master'
Using ListAdapter for PrivateGroupList

See merge request briar/briar!1327
2021-01-05 11:25:33 +00:00
Torsten Grote ff70315d5c Address small things found in code review
of group list view model migration.
2021-01-04 16:19:29 -03:00
Torsten Grote f197243273 Block all group message notifications while viewing list of private groups 2021-01-04 15:56:37 -03:00
Torsten Grote 6409a3b179 Refactor handleDbException to handleException 2021-01-04 15:39:02 -03:00
Torsten Grote f882e46b33 Make GroupItem immutable and introduce copy constructors 2021-01-04 15:22:31 -03:00
akwizgran efa63c306a Merge branch '1800-db-view-model' into 'master'
Introduce DbViewModel as replacement of DbController

See merge request briar/briar!1326
2021-01-04 14:00:42 +00:00
Torsten Grote 205b4f77b2 Add beginning of a ViewModel test
mostly to demonstrate how those could look like
2020-12-18 14:42:33 -03:00
Torsten Grote 015ecb1d99 Migrate GroupListController to a ViewModel
Use ListAdapter to calculate list diffs on a background thread
2020-12-17 17:40:24 -03:00
Torsten Grote fd86b73626 Load list of private groups in a single DB transaction 2020-12-17 17:40:24 -03:00
Torsten Grote 9048392d4e Add methods to DbViewModel for loading and updating lists of items 2020-12-17 17:40:23 -03:00
Torsten Grote 480aaaa35e Introduce DbViewModel as replacement of DbController 2020-12-16 15:23:05 -03:00
Torsten Grote 002feb8e29 Merge branch '1720-add-up-button-to-feedback-activity' into 'master'
Add "up navigation" button to FeedbackActivity

See merge request briar/briar!1325
2020-12-16 16:52:34 +00:00
akwizgran c6ba2b037a Add "up navigation" button to FeedbackActivity. 2020-12-16 16:04:08 +00:00
Torsten Grote 98788c7c80 Define manifest <queries> allowing us to make intent queries on API 30+ 2020-12-14 12:01:56 -03:00
Torsten Grote e6f66ebc95 Screen overlay warning: remove ability to query and remember allowed apps for API 30+
as we can't query all installed apps anymore when targeting API 30
2020-12-14 10:53:12 -03:00
akwizgran 04485e58da Merge branch '1720-no-acra' into 'master'
Remove ACRA and implement the few bits we need ourselves

Closes #1114, #1720, and #1793

See merge request briar/briar!1319
2020-12-14 13:34:11 +00:00
Torsten Grote 97118fd92b Kill crash reporter process only with some delay 2020-12-14 09:14:42 -03:00
akwizgran ac4fbf202f Fix duplicate DeviceInfo key. 2020-12-11 16:40:55 +00:00
akwizgran b81495eac1 Use JSON bools and numbers, use fixed format for dates, normalise JSON keys. 2020-12-11 16:30:29 +00:00
akwizgran db90f75d2e Remove unused string, remove periods from single-sentence toasts. 2020-12-11 16:29:29 +00:00
Torsten Grote bed3abfd40 Address review feedback for ACRA replacement 2020-12-11 10:50:39 -03:00
Torsten Grote 0967f6c48e Merge branch '1794-tell-tor-about-ipv6-only-networks' into 'master'
Tell Tor when we're on an IPv6-only network

Closes #1794

See merge request briar/briar!1320
2020-12-10 18:24:45 +00:00
Torsten Grote f9a8fcb207 Move Android version from basic info to device info
because the basic info is always sent and we say there won't be data of the device in what we send.
2020-12-10 14:40:33 -03:00
Torsten Grote eb3c2a3566 Remove ACRA and implement the few bits we need ourselves 2020-12-10 14:29:25 -03:00
Torsten Grote 8d735b3023 Merge branch 'tor-0.3.5.12' into 'master'
Upgrade Tor to 0.3.5.12

Closes #1849

See merge request briar/briar!1298
2020-11-16 14:42:30 +00:00
akwizgran b24a0e4bc3 Upgrade Tor to 0.3.5.12. 2020-11-16 13:29:24 +00:00
akwizgran 07da91a6f5 Merge branch 'gradle-plugin-4.1' into 'master'
Upgrade Gradle plugin to 4.1.1

See merge request briar/briar!1296
2020-11-11 17:45:47 +00:00
akwizgran e4e0e712dc Update translations. 2020-11-11 16:59:08 +00:00
Torsten Grote 9294794448 Merge branch '1841-keep-dependency-injection-annotations' into 'master'
Keep dependency injection annotations at runtime

Closes #1841

See merge request briar/briar!1297
2020-11-11 16:54:44 +00:00
akwizgran 5a9958793d Keep dependency injection annotations at runtime. 2020-11-11 16:43:16 +00:00
akwizgran 651d2ca377 Add comment to explain suppressed warning. 2020-11-11 14:22:20 +00:00
akwizgran ecd64f08cd Upgrade Gradle plugin to 4.1.1. 2020-11-11 12:33:36 +00:00
akwizgran f3bffb6aa6 Fix some more lint errors. 2020-11-10 17:48:48 +00:00
akwizgran 33331dee3e Fix some lint errors and warnings. 2020-11-10 17:30:53 +00:00
akwizgran 641525fa74 Upgrade Android and Kotlin dependencies, Gradle Witness. 2020-11-10 16:57:51 +00:00
akwizgran 4b82079e33 Upgrade Gradle plugin to 4.1. 2020-11-10 15:18:50 +00:00
akwizgran caa55ffa14 Merge branch 'android-studio-4.1-update-run-configurations' into 'master'
Update run configurations for Android Studio 4.1

See merge request briar/briar!1295
2020-11-09 13:49:28 +00:00
akwizgran 47ae594921 Update run configurations for Android Studio 4.1. 2020-11-09 12:43:29 +00:00
akwizgran a17b154024 Update translations. 2020-11-09 12:42:13 +00:00
akwizgran 02ee678bab If using bridges, use meek if the network is IPv6-only. 2020-11-03 13:52:12 +00:00
akwizgran f6bdbb1b80 Let Tor know if we're on an IPv6-only network. 2020-11-03 13:44:57 +00:00
Torsten Grote 64e1975cf1 Merge branch 'adaptive-icon' into 'master'
Add adaptive icon for API 26+ and Play Store icon

Closes #1456

See merge request briar/briar!1293
2020-11-03 11:55:12 +00:00
akwizgran 993502add0 Add adaptive icon for API 26+ and Play Store icon. 2020-11-03 11:35:53 +00:00
akwizgran 54893d2716 Bump version numbers for 1.2.12 release. 2020-11-02 14:51:34 +00:00
akwizgran 84657127b8 Update translations. 2020-11-02 14:50:06 +00:00
akwizgran 01a146ba71 Merge branch '1647-illegal-state' into 'master'
Fix IllegalStateException when creating image attachments

Closes #1647

See merge request briar/briar!1187
2020-10-30 16:17:20 +00:00
akwizgran a30e5b672e Merge branch '1592-image-placeholders' into 'master'
Show Attachment Placeholders

Closes #1592

See merge request briar/briar!1186
2020-10-30 15:54:25 +00:00
Torsten Grote edb584dc3b Merge branch 'add-contacts-via-bluetooth' into 'master'
Add contacts via Bluetooth if possible

See merge request briar/briar!1292
2020-10-29 16:54:05 +00:00
akwizgran 12a8907c8b Ignore missing location permission on API < 23 where it's not needed. 2020-10-29 14:34:10 +00:00
akwizgran e0f381a973 Try all transports in order of preference. 2020-10-29 11:48:10 +00:00
Torsten Grote 61d3d133e8 Merge branch '1147-only-alice-performs-discovery' into 'master'
Only Alice should perform Bluetooth discovery

See merge request briar/briar!1291
2020-10-28 11:11:34 +00:00
akwizgran 0caa522f07 Remove error message, return to intro fragment when retrying. 2020-10-27 17:37:22 +00:00
akwizgran 948212103c Require Bluetooth permissions if device supports Bluetooth. 2020-10-27 16:24:34 +00:00
akwizgran ce1a57c2b4 Prefer Bluetooth for adding contacts. 2020-10-27 16:24:33 +00:00
akwizgran 922a52bf83 Only Alice should perform Bluetooth discovery. 2020-10-27 16:21:30 +00:00
akwizgran 8cbb38ee68 Bump version numbers for 1.2.11 release. 2020-10-14 13:15:29 +01:00
akwizgran 1c4cf7d771 Update translations. 2020-10-14 13:14:05 +01:00
akwizgran 090a1bd84e Merge branch '1781-change-alias' into 'master'
Add method to change contact alias to REST API

Closes #1781

See merge request briar/briar!1286
2020-10-14 11:47:10 +00:00
Nico Alt 44f6f5d416 Add method to change contact alias to REST API
Needed for https://code.briarproject.org/briar/briar-gtk/-/issues/14 and
https://code.briarproject.org/briar/python-briar-wrapper/-/issues/6.

Fixes #1781
2020-10-13 23:33:26 +02:00
Torsten Grote b88f012880 Merge branch 'make-crash-report-text-selectable' into 'master'
Make the text of crash reports selectable

See merge request briar/briar!1290
2020-10-13 16:23:49 +00:00
akwizgran 93f434e54b Merge branch '1782-delete-all-messages' into 'master'
Add method to delete all private messages to REST API

Closes #1782

See merge request briar/briar!1287
2020-10-13 15:46:01 +00:00
akwizgran 92f4a3a404 Make the text of crash reports selectable.
This makes it possible for users to send device data by other means if
they can't connect to Tor to send a crash report.
2020-10-13 16:44:43 +01:00
Nico Alt c017a813b0 Add output of DeletionResult to deleteAllMessages call 2020-10-08 15:03:49 +02:00
Nico Alt 6c6dbfd357 Add method to delete all private messages to REST API
Needed for https://code.briarproject.org/briar/briar-gtk/-/issues/11.

Fixes #1782
2020-10-08 14:03:16 +02:00
akwizgran 1f246637e2 Merge branch 'kotlin-no-star-imports' into 'master'
Change Kotlin coding style to not do star imports

See merge request briar/briar!1289
2020-10-05 13:54:51 +00:00
Torsten Grote 1ac17cf859 [headless] Change coding style to not do star imports 2020-10-05 09:54:35 -03:00
akwizgran 0a3ff41feb Merge branch '1780-mark-as-read' into 'master'
Add method to mark message as read to REST API

Closes #1780

See merge request briar/briar!1285
2020-10-05 11:38:33 +00:00
Nico Alt 9738dd2838 Add method to mark message as read to REST API
When exposing unread messages counters in
https://code.briarproject.org/briar/briar/-/merge_requests/1283, I
noticed that they were never set to 0.

Fixes #1780
2020-10-03 23:23:54 +02:00
akwizgran be0e21d39b Merge branch '1507-extract-tor-binaries-to-lib-dir' into 'master'
Raise targetSdkVersion to 29, package Tor binaries as libraries

Closes #1507 and #1185

See merge request briar/briar!1279
2020-09-29 13:19:42 +00:00
Torsten Grote 6a2c2bed0f Merge branch '1785-bluetooth-adapter-npe' into 'master'
Check whether Bluetooth adapter exists before trying to get address

Closes #1785

See merge request briar/briar!1288
2020-09-29 12:51:22 +00:00
akwizgran de9c6d4447 Extract version constants into top-level build file. 2020-09-29 13:50:17 +01:00
akwizgran 37a2d9f990 Extract binaries even if older versions already exist. 2020-09-29 13:48:45 +01:00
akwizgran 0e1fb406b5 Extract library filenames into constants. 2020-09-29 13:48:45 +01:00
akwizgran b72e8fa490 Package Tor binaries as libraries so we're allowed to execute them. 2020-09-29 13:48:45 +01:00
akwizgran f3157e5276 Raise target SDK version to 29. 2020-09-29 13:48:43 +01:00
akwizgran e2124ff3c9 Merge branch '1779-headless-messages-sent-acked' into 'master'
Expose message delivery state changes to websockets API

Closes #1779

See merge request briar/briar!1284
2020-09-29 12:46:41 +00:00
akwizgran 66cc9d25e7 Merge branch '1746-headless-unread-counter' into 'master'
Expose unread messages count in API's contacts list

Closes #1746

See merge request briar/briar!1283
2020-09-29 12:45:30 +00:00
akwizgran e9cdec95e0 Check whether Bluetooth adapter exists before trying to get address. 2020-09-29 13:39:46 +01:00
Nico Alt 63d3a78dda Expose message delivery state changes to websockets API
We already indicate whether a message was sent/acked, but we don't
inform about updates.

Needed for briar-gtk#69.

Fixes #1779
2020-09-25 22:39:40 +02:00
Nico Alt ccbe6d4bb8 Expose unread messages count in API's contacts list
Fixes #1746
2020-09-25 17:46:55 +02:00
akwizgran 54b852db70 Bump version numbers for 1.2.10 release. 2020-09-25 13:42:28 +01:00
akwizgran 8d55ea3f6f Update translations. 2020-09-25 13:41:31 +01:00
Torsten Grote 4e5f2e31df Merge branch 'deterministic-briar-headless-jar' into 'master'
Make briar-headless.jar deterministic

See merge request briar/briar!1282
2020-09-17 20:25:12 +00:00
akwizgran 518c0370c8 Make briar-headless.jar deterministic. 2020-09-17 16:13:01 +01:00
akwizgran 7ef2fb5f0c Update Dutch translation. 2020-09-17 14:55:11 +01:00
akwizgran 1210b27bd1 Update translations. 2020-09-17 14:48:10 +01:00
Torsten Grote cdf1a4abcd Merge branch 'update-feed-manager-integration-test-expectations' into 'master'
Update FeedManagerIntegrationTest expectations

See merge request briar/briar!1281
2020-09-10 15:05:39 +00:00
akwizgran b18ef7e72d Update FeedManagerIntegrationTest expectations.
The "Schneier on Security" RSS feed no longer has a description.
2020-09-10 15:56:26 +01:00
Torsten Grote 48d907dda5 Merge branch '185-transports-activity' into 'master'
Add connections screen with information about transports

Closes #185

See merge request briar/briar!1277
2020-09-04 12:27:52 +00:00
akwizgran 3e5b7f451a Merge branch '1716-duplicate-unlock-screen' into 'master'
Don't show duplicate unlock screen on API 29+

Closes #1716

See merge request briar/briar!1280
2020-09-04 12:07:46 +00:00
akwizgran 95cccd1d15 Don't show duplicate unlock screen on API 29+. 2020-09-04 12:37:00 +01:00
Torsten Grote 0a33c77393 Merge branch 'cancel-rendezvous-polling' into 'master'
Only run the rendezvous polling task when we have pending contacts

See merge request briar/briar!1276
2020-09-01 11:53:16 +00:00
Torsten Grote 80caa7634a Merge branch 'do-not-enable-or-disable-bluetooth-automatically' into 'master'
Don't enable or disable the Bluetooth adapter automatically

Closes #1348

See merge request briar/briar!1278
2020-08-14 17:17:22 +00:00
akwizgran 2a8778d3cc Don't enable or disable the Bluetooth adapter automatically. 2020-08-14 16:18:02 +01:00
akwizgran 2cf146a104 Initialise Bluetooth state when view model is created. 2020-08-14 16:13:29 +01:00
akwizgran a1e3c81bda Remove unused drawable. 2020-08-14 15:45:34 +01:00
akwizgran bbcb183c24 Use a single click target that covers all transport indicators. 2020-08-14 15:25:52 +01:00
akwizgran 7fcb3394ca Add optional summary text to transport cards. 2020-08-14 15:25:51 +01:00
akwizgran 4310e4d1af Add help button to transports activity. 2020-08-14 15:25:51 +01:00
akwizgran 82e85bdb39 Remove redundant separator. 2020-08-14 15:25:51 +01:00
akwizgran 5ba0728abc Add onboarding for transports activity. 2020-08-14 15:25:51 +01:00
akwizgran 46bdb3589c Use Briar card style (sets background colour for dark theme). 2020-08-14 15:25:51 +01:00
akwizgran 392bc0d339 Use resource for title of transports activity. 2020-08-14 15:25:51 +01:00
akwizgran 02cf6bfcaa Use constants for default settings. 2020-08-14 15:25:51 +01:00
akwizgran 08a8a0b281 Show reason why Tor is disabled. 2020-08-14 15:25:51 +01:00
akwizgran b189a38f62 Only show plugin status when it's relevant. 2020-08-14 15:25:50 +01:00
akwizgran 57b0641e5f Update network status. 2020-08-14 15:25:50 +01:00
akwizgran 5b5d513316 Shorter explanations. 2020-08-14 15:25:50 +01:00
akwizgran 6684fb2e1b Add settings button to toolbar. 2020-08-14 15:25:50 +01:00
akwizgran 73c6a29ede Add transports activity. 2020-08-14 15:25:50 +01:00
akwizgran a8fe0a01ac Only run the rendezvous polling task when we have pending contacts. 2020-08-14 14:49:04 +01:00
Torsten Grote c75c8da4b9 Merge branch '1759-fix-periodic-task-cancellation' into 'master'
Fix cancellation of periodic tasks, remove ticker

Closes #1759

See merge request briar/briar!1274
2020-08-14 12:47:20 +00:00
Torsten Grote 2f3f3d256c Merge branch '1745-try-to-bind-on-connectivity-change' into 'master'
Try to bind IPv4 and IPv6 sockets whenever connectivity changes

Closes #1745

See merge request briar/briar!1275
2020-08-14 11:24:18 +00:00
Torsten Grote 1141d01dc7 Merge branch '1758-release-timeout-monitor-resources' into 'master'
Ensure TimeoutInputStreams are closed

Closes #1758

See merge request briar/briar!1273
2020-08-14 11:00:49 +00:00
akwizgran e06eee2358 Try to bind IPv4 and IPv6 sockets whenever connectivity changes. 2020-08-14 10:44:33 +01:00
akwizgran c37fe2a246 Fix cancellation of periodic tasks, remove ticker. 2020-08-13 16:35:32 +01:00
akwizgran 79ad5ca07e Ensure TimeoutInputStreams are closed. 2020-08-13 16:35:03 +01:00
akwizgran 0e2d905486 Merge branch '1142-wakeful-lifecycle' into 'master'
Hold a wake lock during app startup and shutdown

See merge request briar/briar!1271
2020-08-13 15:33:09 +00:00
akwizgran 6094014487 Add a comment discouraging use of dedicated threads. 2020-08-13 16:23:44 +01:00
akwizgran 9603ff93e9 Don't sign out when panic button is triggered if configured not to. 2020-08-13 10:19:33 +01:00
akwizgran e7ac6aef8c Improve readability. 2020-08-13 10:14:13 +01:00
Torsten Grote 4e18115d88 Merge branch '1721-fine-location' into 'master'
Request fine location permission for Bluetooth discovery

Closes #1721

See merge request briar/briar!1272
2020-08-12 19:40:48 +00:00
akwizgran b57fb9c842 Request fine location permission for Bluetooth discovery. 2020-08-12 17:29:47 +01:00
akwizgran 196a2b7e22 Fix constructor arguments in unit test. 2020-08-12 17:19:13 +01:00
akwizgran 37712203d7 Hold a wake lock while signing out. 2020-08-12 16:47:02 +01:00
akwizgran cc67237893 Don't redundantly use wakeful IO executor. 2020-08-12 16:47:02 +01:00
akwizgran 79f3a77e1a Annotate methods that should be called with a wake lock. 2020-08-12 16:47:02 +01:00
akwizgran 3ecec61c25 Hold a wake lock while starting plugins. 2020-08-12 16:47:02 +01:00
akwizgran 1e2dc862ef Hold a wake lock during app startup and shutdown. 2020-08-12 16:47:02 +01:00
akwizgran 452c3afbb3 Merge branch '1142-inject-plugin-factories' into 'master'
Use injection to create plugin factories

See merge request briar/briar!1270
2020-08-12 15:46:02 +00:00
akwizgran 9d60fbe957 Merge branch '1142-wakeful-polling' into 'master'
Hold a wake lock while polling

See merge request briar/briar!1269
2020-08-12 15:45:08 +00:00
akwizgran 434b8a37f3 Use wakeful IO executor for polling, reconnection tasks. 2020-08-10 17:24:04 +01:00
akwizgran 5e6a382b4b Merge branch '1142-wakeful-tasks' into 'master'
Hold a wake lock while running scheduled tasks

See merge request briar/briar!1268
2020-08-10 12:54:00 +00:00
akwizgran b5bb4aff7f Merge branch 'master' into '1142-wakeful-tasks'
# Conflicts:
#   bramble-android/src/main/java/org/briarproject/bramble/system/AndroidTaskScheduler.java
2020-08-10 12:37:50 +00:00
akwizgran b0bf9d5a8c Merge branch '1142-wake-lock-refactoring' into 'master'
Share a single wake lock among all holders

See merge request briar/briar!1267
2020-08-10 12:36:06 +00:00
akwizgran 1e6fd8bb74 Merge branch '1142-scheduler-interface' into 'master'
Use TaskScheduler for scheduling tasks

See merge request briar/briar!1266
2020-08-10 10:36:56 +00:00
akwizgran eac93f43d3 Add comments for wake lock handling. 2020-08-10 11:36:05 +01:00
akwizgran 23f22af6e4 Add a comment, wrap logging in an if. 2020-08-10 11:26:29 +01:00
akwizgran 6e8e955dc2 Update javadocs. 2020-08-07 16:16:31 +01:00
akwizgran 2e2bc2d82f Remove @Immutable annotation, which is no longer true. 2020-08-07 15:51:15 +01:00
akwizgran 1af951f8b4 Use injection to create plugin factories. 2020-08-07 15:11:03 +01:00
akwizgran 086c10abc0 Hold wake lock while polling. 2020-08-07 15:10:18 +01:00
akwizgran b5341700be Add wakeful IO executor. 2020-08-07 15:10:18 +01:00
akwizgran d8be340120 Use a unique log tag for each wake lock instance. 2020-08-07 15:09:14 +01:00
akwizgran 7e0d21de38 Add tags for wake lock holders. 2020-08-07 15:09:13 +01:00
akwizgran 1bab15baaf Add fine logging for wake locks. 2020-08-07 15:09:13 +01:00
akwizgran af1a91c819 Fix circular dependency between scheduler and wake lock manager. 2020-08-07 15:09:13 +01:00
akwizgran e6c3f82fe2 Fix test expectations. 2020-08-07 15:09:13 +01:00
akwizgran b2840c1b00 Add method for executing a task on an executor wakefully. 2020-08-07 15:09:13 +01:00
akwizgran 942bb28701 Hold a wake lock while running due tasks. 2020-08-07 15:09:11 +01:00
akwizgran 94dd0a2661 Hold a wake lock while scheduled tasks are running. 2020-08-07 15:08:53 +01:00
akwizgran 3aa00ecb3d Pass executor to scheduler. 2020-08-07 15:08:53 +01:00
akwizgran d5395d3d01 Shared wake lock must be a singleton. 2020-08-07 15:07:48 +01:00
akwizgran b6b721e3b1 Use a wider safety margin to allow for scheduler delays. 2020-08-07 15:02:50 +01:00
akwizgran 7cdd05fd67 Log a warning if the wake lock expires before it's renewed. 2020-08-07 15:02:49 +01:00
akwizgran 286f6f492c Share a single OS wake lock among all holders. 2020-08-07 15:02:49 +01:00
akwizgran eb6b4aa850 Move wake lock properties into factory. 2020-08-07 15:02:49 +01:00
akwizgran adb657a5b6 Ensure we only call openOutputStream() once. 2020-08-07 15:02:49 +01:00
akwizgran d794777eb2 Refactor wake lock creation. 2020-08-07 15:02:49 +01:00
akwizgran 090123579d Use elapsed time since boot rather than wall clock time. 2020-08-07 15:02:05 +01:00
akwizgran f1bde4e75c Fixed delay is easier to reconcile with sleeps than fixed rate. 2020-08-07 15:02:05 +01:00
akwizgran ac80a90ef3 Add Android task scheduler. 2020-08-07 15:02:05 +01:00
akwizgran dfefb88b32 Allow Android and headless to use different task schedulers. 2020-08-07 15:02:05 +01:00
akwizgran 86641741a0 Wrap scheduler in an interface. 2020-08-07 15:02:05 +01:00
Torsten Grote 280f87065e Merge branch 'reflected-bt-address' into 'master'
Use reflected BT address if we don't know our own address

See merge request briar/briar!1265
2020-08-07 13:59:00 +00:00
akwizgran cbe645a4a3 Merge branch 'reflected-transport-properties' into 'master'
Reflect discovered transport properties back to the remote peer

See merge request briar/briar!1264
2020-08-07 13:46:52 +00:00
akwizgran f4e9e10245 Remove unused constants. 2020-07-21 17:07:37 +01:00
akwizgran e9f78bc486 Avoid redundantly storing unchanged properties and settings. 2020-07-21 17:06:02 +01:00
akwizgran a4091be6f7 Ignore reflected address until we've made a Bluetooth connection.
This reduces the opportunities for contacts to reflect a false address.
2020-07-21 17:06:02 +01:00
akwizgran 49f0640278 Use reflected Bluetooth address if we don't know our own address. 2020-07-21 17:06:02 +01:00
akwizgran d617e67006 Add method for plugins to get remote properties. 2020-07-21 17:06:02 +01:00
akwizgran 2063f6c57c Don't attach contact ID to RemoteTransportPropertiesUpdatedEvent. 2020-07-21 17:05:41 +01:00
akwizgran f68d8d284f Merge branch 'master' into 'reflected-transport-properties'
# Conflicts:
#   bramble-core/src/main/java/org/briarproject/bramble/properties/TransportPropertyManagerImpl.java
2020-07-21 09:18:29 +00:00
Torsten Grote 3c63fecb5d Merge branch 'v3-hidden-service-migration' into 'master'
Use v3 hidden services (alongside v2 if a service already exists)

See merge request briar/briar!1263
2020-07-20 16:55:08 +00:00
akwizgran 41fdd584ad Test whether event is attached to transaction. 2020-07-17 17:37:22 +01:00
akwizgran 1b37dceb28 Only add the onion hostname to transport properties once. 2020-07-17 16:55:30 +01:00
akwizgran c183ca0340 Fix a lint warning. 2020-07-17 16:53:26 +01:00
akwizgran 90e91221d9 Reflect discovered properties back to the remote peer. 2020-07-16 14:25:43 +01:00
akwizgran b91fe66461 Broadcast an event when remote transport properties are updated. 2020-07-16 11:38:55 +01:00
akwizgran b5ab077afa Merge branch 'htmlcompat' into 'master'
Replace deprecated Html#fromHtml with HtmlCompat#fromHtml.

Closes #1435

See merge request briar/briar!1262
2020-07-14 09:39:21 +00:00
Tobias Preuss 496d4188c7 Replace deprecated Html#fromHtml with HtmlCompat#fromHtml.
Resolves #1435.
2020-07-13 19:52:22 +02:00
Torsten Grote ab682c82a3 Merge branch 'translation-md' into 'master'
Add TRANSLATION.md file

See merge request briar/briar!1261
2020-07-10 13:31:24 +00:00
akwizgran 375a7276ad Add link to LocLab wiki. 2020-07-10 14:22:06 +01:00
akwizgran b7084b2486 Add TRANSLATION.md file.
This was recommended by Translate House.
2020-07-10 11:19:57 +01:00
akwizgran aa152a80d1 Merge branch 'headless-connected' into 'master'
Expose contact connected state to REST API

See merge request briar/briar!1260
2020-07-06 14:50:57 +00:00
Torsten Grote 3f0d9233d9 [headless] expose contact connected state to REST API 2020-07-06 08:21:07 -03:00
akwizgran 9d96ce6db0 Bump version numbers for 1.2.9 release. 2020-07-04 22:40:58 +01:00
akwizgran 45fb5bb445 Merge branch 'expiry-overflow-bug' into 'master'
Fix overflow in expiry warning code, bypass expiry code in release builds

See merge request briar/briar!1259
2020-07-04 21:38:22 +00:00
akwizgran 0756d92ca1 Fix overflow in expiry warning code, bypass code in release builds. 2020-07-04 22:23:06 +01:00
akwizgran 37f80c7682 Bump version numbers for 1.2.8 release. 2020-07-03 16:03:50 +01:00
akwizgran b409215c57 Update translations. 2020-07-03 15:57:47 +01:00
Torsten Grote 4f0aaf03fd Merge branch '1744-check-socket-is-bound' into 'master'
Check server socket is bound

Closes #1744

See merge request briar/briar!1258
2020-07-03 14:51:05 +00:00
akwizgran 597fef6d50 Check server socket is bound. 2020-07-03 13:04:26 +01:00
akwizgran c1d0936a1e Log HS version when descriptor is uploaded. 2020-06-30 14:18:55 +01:00
akwizgran 717be0178a Allow local transport properties to be removed by setting empty values. 2020-06-30 14:05:46 +01:00
akwizgran 34677eb3a7 Migrate to v3 hidden services. 2020-06-30 12:22:16 +01:00
akwizgran 1dd15567de Merge branch 'style-guide-colours' into 'master'
Use colours from style guide

See merge request briar/briar!1257
2020-06-29 17:09:41 +00:00
akwizgran 428f06abdd Use style guide colours in drawables. 2020-06-29 17:58:10 +01:00
Torsten Grote e1d1c62708 Merge branch 'default-plugin-settings' into 'master'
Enable LAN plugin by default, move default settings to constants

See merge request briar/briar!1256
2020-06-29 16:52:51 +00:00
akwizgran ae75090d23 Use colours from style guide. 2020-06-29 17:20:42 +01:00
Torsten Grote 443043ae09 Merge branch 'plugin-toggles' into 'master'
Merge plugin-toggles feature branch

See merge request briar/briar!1255
2020-06-29 13:07:52 +00:00
akwizgran fb85730b8e Enable LAN by default, as on master.
Let's not break too many things at once.
2020-06-26 17:42:05 +01:00
akwizgran 48b1e77065 Use constants for default plugin settings. 2020-06-26 17:42:05 +01:00
akwizgran a03953563f Show appropriate text for answered introduction requests. 2020-06-26 17:37:17 +01:00
akwizgran 033fd2d3b4 Update comments about migration periods, since this isn't merged yet. 2020-06-26 17:37:16 +01:00
akwizgran 011d8e1df7 Remove unused strings. 2020-06-26 17:37:16 +01:00
akwizgran ef5e2dad72 Make inner class just a holder for resources. 2020-06-26 17:37:16 +01:00
akwizgran f35e87c8ad Remove unused code, fix a null safety bug. 2020-06-26 17:37:16 +01:00
akwizgran e4940a046a Move transport toggles back to the settings screen. 2020-06-26 17:37:16 +01:00
akwizgran 0a666df164 Correctly handle connectivity events on IPv6-only networks. 2020-06-26 17:37:16 +01:00
akwizgran 6fb4b95b18 Don't allow list elements to be null. 2020-06-26 17:37:16 +01:00
akwizgran 5567982fb4 Use IPv6 for key agreement if IPv4 isn't available. 2020-06-26 17:37:16 +01:00
akwizgran 25e50ceb10 Try to detect our address on an IPv6-only wifi network. 2020-06-26 17:37:16 +01:00
akwizgran 1495daf977 Remove redundant address checks.
Remote addresses are checked for acceptability before connecting.
2020-06-26 17:37:16 +01:00
akwizgran badc6da649 Accept any link-local IPv6 address.
This allows IPv6 to be used when providing an access point.
2020-06-26 17:37:16 +01:00
akwizgran e065d45d16 Recognise unusual AP addresses. 2020-06-26 17:37:16 +01:00
akwizgran d0c53f1310 Only bind to the SLAAC address of the wifi interface.
This is just a precaution - on all devices I've tested, the wifi
interface is the only one with a SLAAC address.
2020-06-26 17:37:16 +01:00
akwizgran e1084ffadd Support IPv6 SLAAC addresses. 2020-06-26 17:37:15 +01:00
akwizgran 2bd2f67693 Interrupt sync sessions when transport becomes inactive.
This ensures connections are closed when the user disables a transport.
2020-06-26 17:37:12 +01:00
akwizgran c2b0a4b8d1 Remove unnecessary plugin lookup. 2020-06-26 17:34:38 +01:00
akwizgran ee19d2f574 Use tinted icon for plugin settings dialog. 2020-06-26 17:34:38 +01:00
akwizgran e9ec5734e2 Show dialog from controller. 2020-06-26 17:34:38 +01:00
akwizgran 7b1c6f3fdd Add icon, title to Change Settings dialog. 2020-06-26 17:34:38 +01:00
akwizgran d689cf776c Change Tor settings after asking for confirmation. 2020-06-26 17:34:38 +01:00
akwizgran f0fd1844dd Transition from one constraint set to another. 2020-06-26 17:34:38 +01:00
akwizgran d16a301fc4 Make entire collapsed view clickable. 2020-06-26 17:34:38 +01:00
akwizgran 3ab88181eb Put the transport toggles in an expandable view (no animations). 2020-06-26 17:34:37 +01:00
akwizgran 802e599f09 Add STARTING_STOPPING state, use flags for reasons disabled. 2020-06-26 17:34:37 +01:00
akwizgran a6bd59d3c9 Close small gap between setStarted() and setDisabledBySettings(). 2020-06-26 17:34:37 +01:00
akwizgran b04b724028 Don't show Tor in the enabling state if it's disabled by settings. 2020-06-26 17:34:37 +01:00
akwizgran 71b0408fe6 Remove "don't connect" option from Tor network setting.
This has been replaced by the enable/disable setting and no longer
works.
2020-06-26 17:34:37 +01:00
Torsten Grote 2d38bd5734 [android] Scroll down when nav drawer chevron is pressed 2020-06-26 17:34:37 +01:00
Torsten Grote ff5da8404a [android] remove unused strings 2020-06-26 17:34:37 +01:00
Torsten Grote 75615a4e7f [android] make transport plugin toggles functional 2020-06-26 17:34:37 +01:00
Torsten Grote 96e32ad64e [android] Add transport plugin toggles to NavDrawer 2020-06-26 17:34:37 +01:00
Torsten Grote 0fec5d7783 [bramble] Add method for enabling/disabling plugins to PluginManager 2020-06-26 17:34:37 +01:00
akwizgran ee74b3774b Remove another redundant call to pluginStateChanged(). 2020-06-26 17:34:37 +01:00
akwizgran c783a2f352 Enable LAN plugin before showing QR code. 2020-06-26 17:34:37 +01:00
akwizgran 77aa5401f3 Remove redundant call to pluginStateChanged(). 2020-06-26 17:34:37 +01:00
akwizgran 99686f5316 Use XML to specify dependencies between settings. 2020-06-26 17:34:37 +01:00
akwizgran f5b4f6e071 Clean up logic for enabling/disabling settings. 2020-06-26 17:34:36 +01:00
akwizgran a2de841e6a Don't remove old settings yet.
This avoids an unlikely race condition at startup, where the user opens
the settings screen before the Tor plugin has migrated the settings.
2020-06-26 17:34:36 +01:00
akwizgran 1f94c2d4e8 Enable LAN plugin in unit test. 2020-06-26 17:34:36 +01:00
akwizgran 413ce29c0c Enable BT plugin before showing QR code. 2020-06-26 17:34:36 +01:00
akwizgran c67f758c90 Small code cleanups in key agreement UI. 2020-06-26 17:34:36 +01:00
akwizgran 339524500b Make REASON_USER into a generic reason code. 2020-06-26 17:34:36 +01:00
akwizgran 03811f78fa Add toggle setting for LAN plugin. 2020-06-26 17:34:36 +01:00
akwizgran fc86c46456 Update semantics of Bluetooth setting.
The setting now enables/disables the plugin, not just contact
connections. The key agreement UI will need to be updated to change the
setting if the user agrees to use Bluetooth.
2020-06-26 17:34:36 +01:00
akwizgran 7ae86d70af Convert Bluetooth setting to a switch. 2020-06-26 17:34:36 +01:00
akwizgran 63e3c661a3 Add toggle setting for Tor plugin. 2020-06-26 17:34:36 +01:00
akwizgran 4f54bd90fb Remove redundant casts. 2020-06-26 17:34:36 +01:00
akwizgran 706c03aa8b Skip fetching RSS feeds if Tor is not active. 2020-06-26 17:34:36 +01:00
akwizgran c42a987927 Use amber icon when enabling transports. 2020-06-26 17:34:36 +01:00
akwizgran 297dbe0b16 Only update bridge and padding settings if network is enabled. 2020-06-26 17:34:35 +01:00
akwizgran 4130662e1f Notify callback of state changes while holding lock. 2020-06-26 17:34:35 +01:00
akwizgran c08bdf96cd Update javadocs for lock-safe methods. 2020-06-26 17:34:35 +01:00
akwizgran 8bb534564f Remove redundant logging. 2020-06-26 17:34:35 +01:00
akwizgran 5e60a717fc Remove debug logging. 2020-06-26 17:34:35 +01:00
akwizgran dd1509350c Close server socket when BT is disabled. 2020-06-26 17:34:35 +01:00
akwizgran 465ba3d337 Remove unnecessary inner class, state checks. 2020-06-26 17:34:35 +01:00
akwizgran 7561c5039e Reset backoff before notifying of new state.
The new state may cause the poller to poll the
plugin. Let's avoid a race between updating and
querying the polling interval.
2020-06-26 17:34:35 +01:00
akwizgran 242d6f8a0e Move to enabling state earlier in Tor startup. 2020-06-26 17:34:35 +01:00
akwizgran c554847b54 Add TransportStateEvent, rename existing events. 2020-06-26 17:34:35 +01:00
akwizgran d30b250389 Ensure server socket is closed. 2020-06-26 17:34:35 +01:00
akwizgran ecea2c587d Add method for getting reason why plugin is disabled. 2020-06-26 17:34:35 +01:00
akwizgran 43a91e2e57 Fix test expectations. 2020-06-26 17:34:35 +01:00
akwizgran ea288b998b Rename available/unavailable states. 2020-06-26 17:34:34 +01:00
akwizgran 48dc598ca3 Update tests. 2020-06-26 17:34:34 +01:00
akwizgran e2d63ac6a4 If adapter is disabled, forget that we enabled it. 2020-06-26 17:34:34 +01:00
akwizgran afc85cdf52 Check that server sockets are closed as expected. 2020-06-26 17:34:34 +01:00
akwizgran b2a1ea84f8 Provide more information about plugin states. 2020-06-26 17:34:32 +01:00
akwizgran fcc26c093b Avoid NPE if there's no TelephonyManager. 2020-06-26 17:33:54 +01:00
Torsten Grote 5a741bf13b Merge branch '1712-bluetooth-connection-wake-lock' into 'master'
Hold a wake lock while Bluetooth connections are open

See merge request briar/briar!1251
2020-06-26 16:11:36 +00:00
akwizgran 5dc460851b Remove redundant logging. 2020-06-26 15:33:37 +01:00
akwizgran b805514f70 Use renewable wake lock, try to guess a "safe" tag. 2020-06-26 14:58:06 +01:00
akwizgran 69d94c9f29 Hold a wake lock while Bluetooth connections are open. 2020-06-26 14:58:06 +01:00
Torsten Grote 53d4b7a0df Merge branch '1712-simple-connection-limiter' into 'master'
Simple connection limiter that closes connections cleanly

Closes #1712

See merge request briar/briar!1254
2020-06-26 11:36:21 +00:00
akwizgran 648f26542c Simple connection limiter that closes connections cleanly. 2020-06-26 10:57:08 +01:00
akwizgran dcb5f95934 Merge branch '1712-prefer-lan-to-bluetooth' into 'master'
Close redundant connections

See merge request briar/briar!1249
2020-06-26 09:46:24 +00:00
akwizgran 730d553b0a Fix screenshot test (again). 2020-06-26 10:38:04 +01:00
akwizgran 7736a3b6fc Use separate methods for registering incoming and outgoing connections. 2020-06-26 09:59:03 +01:00
akwizgran 95f427863d Remove transport preferences for briar-headless. 2020-06-25 17:46:22 +01:00
Torsten Grote ff8a422638 Merge branch '1712-connection-manager-refactoring' into 'master'
Connection manager refactoring

See merge request briar/briar!1248
2020-06-25 14:21:49 +00:00
akwizgran 78d7fc2106 Fix bug in reporting of connection state, add regression tests. 2020-06-02 12:00:06 +01:00
akwizgran cc943be540 Update javadoc. 2020-06-01 15:30:30 +01:00
akwizgran 6eb77465f6 Don't try to reconnect if the connection was closed cleanly. 2020-06-01 14:49:55 +01:00
akwizgran 35d1b406f7 Refactor transport preferences. 2020-06-01 14:49:55 +01:00
akwizgran 2add63657e Inner class can be static. 2020-06-01 14:49:55 +01:00
akwizgran d3751fbead Don't interrupt connections until priority is set.
This maintains compatibility with older peers that don't know about
priorities or transport preferences and will try to replace any
connections we close.
2020-06-01 14:49:55 +01:00
akwizgran 4aaa8c3b93 Don't poll if already connected via a better transport. 2020-05-25 17:47:33 +01:00
akwizgran 5b04527c54 Fix screenshot test. 2020-05-25 17:47:33 +01:00
akwizgran 7d6b65913a Combine connection chooser with connection registry. 2020-05-25 16:42:01 +01:00
akwizgran 36747acac1 Extract better and worse transports from preferences. 2020-05-25 14:47:34 +01:00
akwizgran e8dbc00712 Refactor connection registry implementation. 2020-05-25 14:33:35 +01:00
akwizgran d3d7212b08 Add registry method for deciding which contacts to poll. 2020-05-13 17:55:05 +01:00
akwizgran 2919657b4a Add unit tests for connection chooser. 2020-05-13 15:56:07 +01:00
akwizgran 0c338b362e Add InterruptibleConnection interface for easier testing. 2020-05-13 15:43:07 +01:00
akwizgran 8dd993dd9d Interrupt connections outside the lock. 2020-05-13 10:24:27 +01:00
akwizgran 1b2b50d91b Exchange priority records and close redundant connections. 2020-05-12 21:36:58 +01:00
akwizgran ee9c771045 Add priority record for choosing between redundant connections. 2020-05-12 21:36:58 +01:00
akwizgran 9e6d67f13d Handle interrupts that occur before the outgoing session starts. 2020-05-12 21:36:57 +01:00
akwizgran 710b6d18ce Fix import in screenshot test. 2020-05-12 21:36:45 +01:00
akwizgran dd4aa67643 Refactor connection creation back into manager. 2020-05-12 21:27:43 +01:00
akwizgran 79482d5e3a Move connection management to its own package. 2020-05-12 17:36:35 +01:00
akwizgran ee0bf7218c Move some duplicated code into utility methods. 2020-05-12 17:25:55 +01:00
akwizgran c1101c7fe1 Factor inner classes out of ConnectionManagerImpl. 2020-05-12 17:08:04 +01:00
Torsten Grote 708452713d Merge branch '1712-detect-dead-bluetooth-connections' into 'master'
Detect and close dead Bluetooth connections

See merge request briar/briar!1246
2020-05-11 15:55:07 +00:00
akwizgran c80d3196af Use milliseconds for timing. 2020-05-11 15:42:23 +01:00
Torsten Grote d1c2eb89a1 Merge branch '1712-fix-double-connection-counting' into 'master'
Don't count Bluetooth connections twice

See merge request briar/briar!1245
2020-05-11 14:06:30 +00:00
akwizgran c4273d22ed Delegate all other methods to wrapped InputStream. 2020-05-08 16:22:46 +01:00
akwizgran 21f3a9f3c7 Add javadoc. 2020-05-08 16:22:46 +01:00
akwizgran 0281eec0da Add unit test for TimeoutInputStream. 2020-05-08 16:22:46 +01:00
akwizgran d3fd309609 Only check timeouts when we have some streams to monitor. 2020-05-08 16:22:46 +01:00
akwizgran f2f278c393 Add timeout monitor for Bluetooth connections. 2020-05-08 16:22:46 +01:00
akwizgran e204d5a996 Don't count connections twice. 2020-05-08 15:17:27 +01:00
akwizgran 876efee1a8 Use keepalives to detect dead connections. 2020-05-08 14:21:41 +01:00
Torsten Grote cf8241e79c Fix IllegalStateException in RecyclerView when backing out very quickly
after adding image attachments for preview before sending
2020-02-13 10:28:00 -03:00
Torsten Grote 61d3fe9055 [android] fix IllegalStateException when creating attachments
Injecting the non-singleton AttachmentCreator keeps an instance around
that gets re-used with a different ViewModel.
When backing out without sending or cancelling the attachments,
we don't reset the state which leads us into an illegal state.
2020-02-13 10:28:00 -03:00
Torsten Grote bded1edb2b [android] Use ordinary HashMap for to be received attachments
Also don't do list stacking from end for now.
2020-02-13 10:26:43 -03:00
akwizgran 4d27828712 Check for concurrent cache updates. 2020-02-13 10:26:43 -03:00
Torsten Grote 0f6f52c37a [android] Listen to AttachmentReceivedEvents when ConversationActivity is stopped
This way Attachments get shown when the activity resumes.
2020-02-13 10:26:42 -03:00
Torsten Grote c1cf6f61b9 [android] fix concurrency issues when attachments are received delayed
Do not observe attachment live data multiple times
and don't miss received attachments in ImageActivity resp. ImageViewModel.
2020-02-13 10:26:42 -03:00
Torsten Grote 7c22016b81 [android] attach some smaller image attachment issues 2020-02-13 10:26:42 -03:00
Torsten Grote 31f42d44af [android] Refactor attachment loading to use LiveData 2020-02-13 10:26:42 -03:00
Torsten Grote a1cf485ecc [android] address first round of code review for attachment placeholders 2020-02-13 10:26:41 -03:00
Torsten Grote b7d3cd7990 [android] support attachments arriving *before* the message containing them 2020-02-13 10:26:41 -03:00
Torsten Grote 4122e0852a Show placeholders for missing attachments in ImageActivity
and display attachments as they arrive while ImageActivity is open.
2020-02-13 10:26:41 -03:00
Torsten Grote 41411b0e2e Refactor attachment loading to support incremental display once loaded 2020-02-13 10:26:40 -03:00
1040 changed files with 41845 additions and 17359 deletions
+1
View File
@@ -18,6 +18,7 @@ local.properties
# Android Studio
.idea/*
!.idea/inspectionProfiles/
!.idea/runConfigurations/
!.idea/codeStyleSettings.xml
!.idea/codeStyles
+94 -9
View File
@@ -2,28 +2,78 @@ image: briar/ci-image-android:latest
stages:
- test
- optional_tests
- check_reproducibility
test:
stage: test
workflow:
# when to create a CI pipeline
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never # avoids duplicate jobs for branch and MR
- if: '$CI_COMMIT_BRANCH'
- if: '$CI_COMMIT_TAG'
.base-test:
before_script:
- set -e
- export GRADLE_USER_HOME=$PWD/.gradle
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- .gradle/wrapper
- .gradle/caches
script:
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom check compileOfficialDebugAndroidTestSources compileScreenshotDebugAndroidTestSources
after_script:
# these file change every time but should not be cached
# these file change every time and should not be cached
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
- rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/
test:
extends: .base-test
stage: test
script:
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom check
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- when: always
android test:
extends: .base-test
stage: optional_tests
image: briar/ci-image-android-emulator:latest
script:
# start emulator first, so it can fail early
- start-emulator.sh
# run normal and screenshot tests together (exclude Large tests)
- ./gradlew -Djava.security.egd=file:/dev/urandom connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.package=org.briarproject.briar.android -Pandroid.testInstrumentationRunnerArguments.notAnnotation=androidx.test.filters.LargeTest
after_script:
- adb pull /sdcard/Pictures/screenshots
artifacts:
name: "${CI_PROJECT_PATH}_${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}"
paths:
- kernel.log
- logcat.txt
- briar-android/build/reports/androidTests/connected/flavors/*
- screenshots
expire_in: 3 days
when: on_failure
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
changes:
- briar-android/**/*
when: manual
allow_failure: true
- if: '$CI_COMMIT_TAG == null'
when: manual
allow_failure: true
retry:
max: 1
tags:
- kvm
test_reproducible:
stage: check_reproducibility
@@ -31,3 +81,38 @@ test_reproducible:
- "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/61/trigger/pipeline"
only:
- tags
.optional_tests:
stage: optional_tests
before_script:
- set -e
- export GRADLE_USER_HOME=$PWD/.gradle
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- .gradle/wrapper
- .gradle/caches
script:
- OPTIONAL_TESTS=org.briarproject.bramble.plugin.tor.BridgeTest ./gradlew --info bramble-java:test --tests BridgeTest
after_script:
# these file change every time but should not be cached
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
- rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/
bridge test:
extends: .optional_tests
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success
allow_failure: true
- if: '$CI_COMMIT_TAG == null'
when: manual
allow_failure: true
pre_release_tests:
extends: .optional_tests
only:
- tags
+14 -3
View File
@@ -1,8 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<AndroidXmlCodeStyleSettings>
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
</AndroidXmlCodeStyleSettings>
<JavaCodeStyleSettings>
<option name="ANNOTATION_PARAMETER_WRAP" value="1" />
<option name="IMPORT_LAYOUT_TABLE">
@@ -31,6 +28,20 @@
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value />
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</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>
+15
View File
@@ -0,0 +1,15 @@
<component name="ProjectDictionaryState">
<dictionary name="briar">
<words>
<w>briar</w>
<w>briarproject</w>
<w>emoji</w>
<w>encrypter</w>
<w>identicon</w>
<w>introducee</w>
<w>introducees</w>
<w>introducer</w>
<w>onboarding</w>
</words>
</dictionary>
</component>
+14
View File
@@ -0,0 +1,14 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="MissingOverrideAnnotation" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoreObjectMethods" value="true" />
<option name="ignoreAnonymousClassMethods" value="false" />
</inspection_tool>
<inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
<option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="true" />
<option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="true" />
<option name="SUGGEST_PRIVATE_FOR_INNERS" value="true" />
</inspection_tool>
</profile>
</component>
+2 -1
View File
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar-android" />
<module name="briar.briar-android" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
@@ -13,6 +13,7 @@
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-api" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-headless" run_configuration_type="AndroidJUnit" />
</method>
+4 -10
View File
@@ -1,20 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
<module name="bramble-android" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<module name="briar.bramble-android" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+4 -10
View File
@@ -1,20 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
<module name="bramble-api" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<module name="briar.bramble-api" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+4 -10
View File
@@ -1,20 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<module name="briar.bramble-core" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+4 -9
View File
@@ -1,8 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
<module name="bramble-java" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<module name="briar.bramble-java" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
@@ -10,11 +8,8 @@
<option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+4 -10
View File
@@ -1,20 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar-android" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<module name="briar.briar-android" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+14
View File
@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-api" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.briar-api" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-api" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+4 -10
View File
@@ -1,20 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<module name="briar.briar-core" />
<option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+1 -1
View File
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-headless" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar-headless" />
<module name="briar.briar-headless" />
<option name="PACKAGE_NAME" value="org.briarproject.briar.headless" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="BridgeTest" type="AndroidJUnit" factoryName="Android JUnit" nameIsGenerated="true">
<module name="briar.bramble-java" />
<useClassPathOnly />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.briarproject.bramble.plugin.tor.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="org.briarproject.bramble.plugin.tor" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<envs>
<env name="OPTIONAL_TESTS" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
</envs>
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+4 -10
View File
@@ -1,20 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<module name="briar.bramble-core" />
<option name="PACKAGE_NAME" value="org.briarproject.bramble.db" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.db.H2DatabasePerformanceTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+4 -10
View File
@@ -1,20 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<module name="briar.bramble-core" />
<option name="PACKAGE_NAME" value="org.briarproject.bramble.db" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.db.HyperSqlDatabasePerformanceTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
@@ -0,0 +1,51 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Instrumentation Tests (destroys DB)" type="AndroidTestRunConfigurationType" factoryName="Android Instrumented Tests">
<module name="briar.briar-android" />
<option name="TESTING_TYPE" value="1" />
<option name="METHOD_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="PACKAGE_NAME" value="org.briarproject.briar.android" />
<option name="INSTRUMENTATION_RUNNER_CLASS" value="" />
<option name="EXTRA_OPTIONS" value="-e notAnnotation androidx.test.filters.LargeTest" />
<option name="INCLUDE_GRADLE_EXTRA_OPTIONS" value="true" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
<option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
<option name="FORCE_STOP_RUNNING_APP" value="true" />
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
<option name="DEBUGGER_TYPE" value="Auto" />
<Auto>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Auto>
<Hybrid>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Hybrid>
<Java />
<Native>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Native>
<Profilers>
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
<option name="STARTUP_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Sample Java Methods" />
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
</Profilers>
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
+4 -5
View File
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="briar-headless" type="JetRunConfigurationType" factoryName="Kotlin" singleton="true">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<configuration default="false" name="briar-headless" type="JetRunConfigurationType" singleton="true">
<module name="briar.briar-headless" />
<option name="VM_PARAMETERS" value="" />
<option name="PROGRAM_PARAMETERS" value="-v" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@@ -8,9 +8,8 @@
<option name="PASS_PARENT_ENVS" value="true" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.briar.headless.MainKt" />
<option name="WORKING_DIRECTORY" value="" />
<module name="briar-headless" />
<envs />
<method>
<method v="2">
<option name="Make" enabled="true" />
<option name="Gradle.BeforeRunTask" enabled="true" tasks="jar" externalProjectPath="$PROJECT_DIR$/briar-headless" vmOptions="" scriptParameters="" />
</method>
</configuration>
+9
View File
@@ -0,0 +1,9 @@
Translations for this project are managed through Transifex:
https://transifex.com/otf/briar
If you'd like to volunteer as a translator, please create a Transifex account and request to be
added to the project's translation team. The Localization Lab has some instructions and advice for
translators here:
https://wiki.localizationlab.org/index.php/Briar
+1
View File
@@ -3,3 +3,4 @@ gen
build
.settings
src/main/res/raw/*.zip
src/main/jniLibs
+45 -10
View File
@@ -5,14 +5,18 @@ apply plugin: 'witness'
apply from: 'witness.gradle'
android {
compileSdkVersion 29
buildToolsVersion '29.0.2'
compileSdkVersion 30
buildToolsVersion '30.0.3'
packagingOptions {
doNotStrip '**/*.so'
}
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
versionCode 10207
versionName "1.2.7"
targetSdkVersion 30
versionCode 10302
versionName "1.3.2"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -38,25 +42,27 @@ configurations {
dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
tor 'org.briarproject:tor-android:0.3.5.10@zip'
tor 'org.briarproject:obfs4proxy-android:0.0.11-2@zip'
tor 'org.briarproject:tor-android:0.3.5.13@zip'
tor 'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.24'
compileOnly 'javax.annotation:jsr250-api:1.0'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13.1'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
}
def torBinariesDir = 'src/main/res/raw'
def torLibsDir = 'src/main/jniLibs'
task cleanTorBinaries {
doLast {
delete fileTree(torBinariesDir) { include '*.zip' }
delete fileTree(torLibsDir) { include '**/*.so' }
}
}
@@ -67,8 +73,36 @@ task unpackTorBinaries {
copy {
from configurations.tor.collect { zipTree(it) }
into torBinariesDir
// TODO: Remove after next Tor upgrade, which won't include non-PIE binaries
include 'geoip.zip', '*_pie.zip'
include 'geoip.zip'
}
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'
}
}
}
}
}
dependsOn cleanTorBinaries
@@ -76,5 +110,6 @@ task unpackTorBinaries {
tasks.withType(MergeResources) {
inputs.dir torBinariesDir
inputs.dir torLibsDir
dependsOn unpackTorBinaries
}
@@ -16,6 +16,8 @@
android:label="@string/app_name"
android:supportsRtl="true">
<receiver android:name=".system.AlarmReceiver" />
</application>
</manifest>
@@ -6,6 +6,8 @@ import org.briarproject.bramble.plugin.tor.CircumventionModule;
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.AndroidWakefulIoExecutorModule;
import dagger.Module;
@@ -13,6 +15,8 @@ import dagger.Module;
AndroidBatteryModule.class,
AndroidNetworkModule.class,
AndroidSystemModule.class,
AndroidTaskSchedulerModule.class,
AndroidWakefulIoExecutorModule.class,
CircumventionModule.class,
ReportingModule.class,
SocksModule.class
@@ -0,0 +1,8 @@
package org.briarproject.bramble;
import org.briarproject.bramble.api.system.AlarmListener;
public interface BrambleAppComponent {
AlarmListener alarmListener();
}
@@ -0,0 +1,6 @@
package org.briarproject.bramble;
public interface BrambleApplication {
BrambleAppComponent getBrambleAppComponent();
}
@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.system;
import android.content.Intent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface AlarmListener {
void onAlarm(Intent intent);
}
@@ -0,0 +1,19 @@
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();
}
@@ -0,0 +1,38 @@
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);
}
@@ -1,24 +1,34 @@
package org.briarproject.bramble.network;
import android.annotation.TargetApi;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventExecutor;
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.Scheduler;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.api.system.TaskScheduler.Cancellable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@@ -35,36 +45,47 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static java.net.NetworkInterface.getNetworkInterfaces;
import static java.util.Collections.list;
import static java.util.concurrent.TimeUnit.MINUTES;
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;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidNetworkManager implements NetworkManager, Service {
private static final Logger LOG =
Logger.getLogger(AndroidNetworkManager.class.getName());
getLogger(AndroidNetworkManager.class.getName());
// See android.net.wifi.WifiManager
private static final String WIFI_AP_STATE_CHANGED_ACTION =
"android.net.wifi.WIFI_AP_STATE_CHANGED";
private final ScheduledExecutorService scheduler;
private final TaskScheduler scheduler;
private final EventBus eventBus;
private final Context appContext;
private final AtomicReference<Future<?>> connectivityCheck =
private final Executor eventExecutor;
private final Application app;
private final ConnectivityManager connectivityManager;
private final AtomicReference<Cancellable> connectivityCheck =
new AtomicReference<>();
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile BroadcastReceiver networkStateReceiver = null;
@Inject
AndroidNetworkManager(@Scheduler ScheduledExecutorService scheduler,
EventBus eventBus, Application app) {
AndroidNetworkManager(TaskScheduler scheduler, EventBus eventBus,
@EventExecutor Executor eventExecutor, Application app) {
this.scheduler = scheduler;
this.eventBus = eventBus;
this.appContext = app.getApplicationContext();
this.eventExecutor = eventExecutor;
this.app = app;
connectivityManager = (ConnectivityManager)
requireNonNull(app.getSystemService(CONNECTIVITY_SERVICE));
}
@Override
@@ -79,24 +100,82 @@ class AndroidNetworkManager implements NetworkManager, Service {
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
filter.addAction(WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
appContext.registerReceiver(networkStateReceiver, filter);
app.registerReceiver(networkStateReceiver, filter);
}
@Override
public void stopService() {
if (networkStateReceiver != null)
appContext.unregisterReceiver(networkStateReceiver);
app.unregisterReceiver(networkStateReceiver);
}
@Override
public NetworkStatus getNetworkStatus() {
ConnectivityManager cm = (ConnectivityManager)
appContext.getSystemService(CONNECTIVITY_SERVICE);
if (cm == null) throw new AssertionError();
NetworkInfo net = cm.getActiveNetworkInfo();
NetworkInfo net = connectivityManager.getActiveNetworkInfo();
boolean connected = net != null && net.isConnected();
boolean wifi = connected && net.getType() == TYPE_WIFI;
return new NetworkStatus(connected, wifi);
boolean wifi = false, ipv6Only = false;
if (connected) {
wifi = net.getType() == TYPE_WIFI;
if (SDK_INT >= 23) ipv6Only = isActiveNetworkIpv6Only();
else ipv6Only = areAllAvailableNetworksIpv6Only();
}
return new NetworkStatus(connected, wifi, ipv6Only);
}
/**
* Returns true if the
* {@link ConnectivityManager#getActiveNetwork() active network} has an
* IPv6 unicast address and no IPv4 addresses. The active network is
* assumed not to be a loopback interface.
*/
@TargetApi(23)
private boolean isActiveNetworkIpv6Only() {
Network net = connectivityManager.getActiveNetwork();
if (net == null) {
LOG.info("No active network");
return false;
}
LinkProperties props = connectivityManager.getLinkProperties(net);
if (props == null) {
LOG.info("No link properties for active network");
return false;
}
boolean hasIpv6Unicast = false;
for (LinkAddress linkAddress : props.getLinkAddresses()) {
InetAddress addr = linkAddress.getAddress();
if (addr instanceof Inet4Address) return false;
if (!addr.isMulticastAddress()) hasIpv6Unicast = true;
}
return hasIpv6Unicast;
}
/**
* Returns true if the device has at least one network interface with an
* IPv6 unicast address and no interfaces with IPv4 addresses, excluding
* loopback interfaces and interfaces that are
* {@link NetworkInterface#isUp() down}. If this method returns true and
* the device has internet access then it's via IPv6 only.
*/
private boolean areAllAvailableNetworksIpv6Only() {
try {
Enumeration<NetworkInterface> interfaces = getNetworkInterfaces();
if (interfaces == null) {
LOG.info("No network interfaces");
return false;
}
boolean hasIpv6Unicast = false;
for (NetworkInterface i : list(interfaces)) {
if (i.isLoopback() || !i.isUp()) continue;
for (InetAddress addr : list(i.getInetAddresses())) {
if (addr instanceof Inet4Address) return false;
if (!addr.isMulticastAddress()) hasIpv6Unicast = true;
}
}
return hasIpv6Unicast;
} catch (SocketException e) {
logException(LOG, WARNING, e);
return false;
}
}
private void updateConnectionStatus() {
@@ -104,11 +183,12 @@ class AndroidNetworkManager implements NetworkManager, Service {
}
private void scheduleConnectionStatusUpdate(int delay, TimeUnit unit) {
Future<?> newConnectivityCheck =
scheduler.schedule(this::updateConnectionStatus, delay, unit);
Future<?> oldConnectivityCheck =
Cancellable newConnectivityCheck =
scheduler.schedule(this::updateConnectionStatus, eventExecutor,
delay, unit);
Cancellable oldConnectivityCheck =
connectivityCheck.getAndSet(newConnectivityCheck);
if (oldConnectivityCheck != null) oldConnectivityCheck.cancel(false);
if (oldConnectivityCheck != null) oldConnectivityCheck.cancel();
}
private class NetworkStateReceiver extends BroadcastReceiver {
@@ -0,0 +1,36 @@
package org.briarproject.bramble.plugin.bluetooth;
import android.bluetooth.BluetoothSocket;
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 java.io.IOException;
@NotNullByDefault
class AndroidBluetoothConnectionFactory
implements BluetoothConnectionFactory<BluetoothSocket> {
private final BluetoothConnectionLimiter connectionLimiter;
private final AndroidWakeLockManager wakeLockManager;
private final TimeoutMonitor timeoutMonitor;
AndroidBluetoothConnectionFactory(
BluetoothConnectionLimiter connectionLimiter,
AndroidWakeLockManager wakeLockManager,
TimeoutMonitor timeoutMonitor) {
this.connectionLimiter = connectionLimiter;
this.wakeLockManager = wakeLockManager;
this.timeoutMonitor = timeoutMonitor;
}
@Override
public DuplexTransportConnection wrapSocket(DuplexPlugin plugin,
BluetoothSocket s) throws IOException {
return new AndroidBluetoothTransportConnection(plugin,
connectionLimiter, wakeLockManager, timeoutMonitor, s);
}
}
@@ -1,5 +1,6 @@
package org.briarproject.bramble.plugin.bluetooth;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
@@ -58,7 +59,8 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
class AndroidBluetoothPlugin extends
AbstractBluetoothPlugin<BluetoothSocket, BluetoothServerSocket> {
private static final Logger LOG =
getLogger(AndroidBluetoothPlugin.class.getName());
@@ -66,23 +68,32 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
private static final int MAX_DISCOVERY_MS = 10_000;
private final AndroidExecutor androidExecutor;
private final Context appContext;
private final Application app;
private final Clock clock;
private volatile boolean wasEnabledByUs = false;
private volatile BluetoothStateReceiver receiver = null;
// Non-null if the plugin started successfully
private volatile BluetoothAdapter adapter = null;
private volatile boolean stopDiscoverAndConnect;
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
Executor ioExecutor, AndroidExecutor androidExecutor,
Context appContext, SecureRandom secureRandom, Clock clock,
Backoff backoff, PluginCallback callback, int maxLatency) {
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback,
maxLatency);
BluetoothConnectionFactory<BluetoothSocket> connectionFactory,
Executor ioExecutor,
Executor wakefulIoExecutor,
SecureRandom secureRandom,
AndroidExecutor androidExecutor,
Application app,
Clock clock,
Backoff backoff,
PluginCallback callback,
int maxLatency,
int maxIdleTime) {
super(connectionLimiter, connectionFactory, ioExecutor,
wakefulIoExecutor, secureRandom, backoff, callback,
maxLatency, maxIdleTime);
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.app = app;
this.clock = clock;
}
@@ -94,13 +105,13 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
filter.addAction(ACTION_STATE_CHANGED);
filter.addAction(ACTION_SCAN_MODE_CHANGED);
receiver = new BluetoothStateReceiver();
appContext.registerReceiver(receiver, filter);
app.registerReceiver(receiver, filter);
}
@Override
public void stop() {
super.stop();
if (receiver != null) appContext.unregisterReceiver(receiver);
if (receiver != null) app.unregisterReceiver(receiver);
}
@Override
@@ -122,36 +133,11 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
return adapter != null && adapter.isEnabled();
}
@Override
void enableAdapter() {
if (adapter != null && !adapter.isEnabled()) {
if (adapter.enable()) {
LOG.info("Enabling Bluetooth");
wasEnabledByUs = true;
} else {
LOG.info("Could not enable Bluetooth");
}
}
}
@Override
void disableAdapterIfEnabledByUs() {
if (isAdapterEnabled() && wasEnabledByUs) {
if (adapter.disable()) LOG.info("Disabling Bluetooth");
else LOG.info("Could not disable Bluetooth");
wasEnabledByUs = false;
}
}
@Override
void setEnabledByUs() {
wasEnabledByUs = true;
}
@Override
@Nullable
String getBluetoothAddress() {
String address = AndroidUtils.getBluetoothAddress(appContext, adapter);
if (adapter == null) return null;
String address = AndroidUtils.getBluetoothAddress(app, adapter);
return address.isEmpty() ? null : address;
}
@@ -169,12 +155,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
@Override
DuplexTransportConnection acceptConnection(BluetoothServerSocket ss)
throws IOException {
return wrapSocket(ss.accept());
}
private DuplexTransportConnection wrapSocket(BluetoothSocket s) {
return new AndroidBluetoothTransportConnection(this,
connectionLimiter, s);
return connectionFactory.wrapSocket(this, ss.accept());
}
@Override
@@ -191,10 +172,15 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
try {
s = d.createInsecureRfcommSocketToServiceRecord(u);
s.connect();
return wrapSocket(s);
return connectionFactory.wrapSocket(this, s);
} catch (IOException e) {
IoUtils.tryToClose(s, LOG, WARNING);
throw e;
} catch (NullPointerException e) {
// BluetoothSocket#connect() may throw an NPE under unknown
// circumstances
IoUtils.tryToClose(s, LOG, WARNING);
throw new IOException(e);
}
}
@@ -202,7 +188,16 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
@Nullable
DuplexTransportConnection discoverAndConnect(String uuid) {
if (adapter == null) return null;
if (!discoverSemaphore.tryAcquire()) {
LOG.info("Discover already running");
return null;
}
try {
stopDiscoverAndConnect = false;
for (String address : discoverDevices()) {
if (stopDiscoverAndConnect) {
break;
}
try {
if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubMacAddress(address));
@@ -214,10 +209,19 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
}
}
}
} finally {
discoverSemaphore.release();
}
LOG.info("Could not connect to any devices");
return null;
}
@Override
public void stopDiscoverAndConnect() {
stopDiscoverAndConnect = true;
adapter.cancelDiscovery();
}
private Collection<String> discoverDevices() {
List<String> addresses = new ArrayList<>();
BlockingQueue<Intent> intents = new LinkedBlockingQueue<>();
@@ -226,7 +230,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
filter.addAction(ACTION_DISCOVERY_STARTED);
filter.addAction(ACTION_DISCOVERY_FINISHED);
filter.addAction(ACTION_FOUND);
appContext.registerReceiver(receiver, filter);
app.registerReceiver(receiver, filter);
try {
if (adapter.startDiscovery()) {
long now = clock.currentTimeMillis();
@@ -263,7 +267,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
} finally {
LOG.info("Cancelling discovery");
adapter.cancelDiscovery();
appContext.unregisterReceiver(receiver);
app.unregisterReceiver(receiver);
}
// Shuffle the addresses so we don't always try the same one first
shuffle(addresses);
@@ -1,8 +1,11 @@
package org.briarproject.bramble.plugin.bluetooth;
import android.content.Context;
import android.app.Application;
import android.bluetooth.BluetoothSocket;
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;
@@ -11,12 +14,15 @@ 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 java.security.SecureRandom;
import java.util.concurrent.Executor;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
@@ -25,28 +31,41 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor;
private final Executor ioExecutor, wakefulIoExecutor;
private final AndroidExecutor androidExecutor;
private final Context appContext;
private final AndroidWakeLockManager wakeLockManager;
private final Application app;
private final SecureRandom secureRandom;
private final EventBus eventBus;
private final Clock clock;
private final TimeoutMonitor timeoutMonitor;
private final BackoffFactory backoffFactory;
public AndroidBluetoothPluginFactory(Executor ioExecutor,
AndroidExecutor androidExecutor, Context appContext,
SecureRandom secureRandom, EventBus eventBus, Clock clock,
@Inject
public AndroidBluetoothPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor,
AndroidExecutor androidExecutor,
AndroidWakeLockManager wakeLockManager,
Application app,
SecureRandom secureRandom,
EventBus eventBus,
Clock clock,
TimeoutMonitor timeoutMonitor,
BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor;
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.wakeLockManager = wakeLockManager;
this.app = app;
this.secureRandom = secureRandom;
this.eventBus = eventBus;
this.clock = clock;
this.timeoutMonitor = timeoutMonitor;
this.backoffFactory = backoffFactory;
}
@@ -63,12 +82,16 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
@Override
public DuplexPlugin createPlugin(PluginCallback callback) {
BluetoothConnectionLimiter connectionLimiter =
new BluetoothConnectionLimiterImpl();
new BluetoothConnectionLimiterImpl(eventBus);
BluetoothConnectionFactory<BluetoothSocket> connectionFactory =
new AndroidBluetoothConnectionFactory(connectionLimiter,
wakeLockManager, timeoutMonitor);
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
connectionLimiter, ioExecutor, androidExecutor, appContext,
secureRandom, clock, backoff, callback, MAX_LATENCY);
connectionLimiter, connectionFactory, ioExecutor,
wakefulIoExecutor, secureRandom, androidExecutor, app,
clock, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin);
return plugin;
}
@@ -2,9 +2,12 @@ package org.briarproject.bramble.plugin.bluetooth;
import android.bluetooth.BluetoothSocket;
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 java.io.IOException;
import java.io.InputStream;
@@ -17,22 +20,30 @@ import static org.briarproject.bramble.util.AndroidUtils.isValidBluetoothAddress
class AndroidBluetoothTransportConnection
extends AbstractDuplexTransportConnection {
private final BluetoothConnectionLimiter connectionManager;
private final BluetoothConnectionLimiter connectionLimiter;
private final BluetoothSocket socket;
private final InputStream in;
private final AndroidWakeLock wakeLock;
AndroidBluetoothTransportConnection(Plugin plugin,
BluetoothConnectionLimiter connectionManager,
BluetoothSocket socket) {
BluetoothConnectionLimiter connectionLimiter,
AndroidWakeLockManager wakeLockManager,
TimeoutMonitor timeoutMonitor,
BluetoothSocket socket) throws IOException {
super(plugin);
this.connectionManager = connectionManager;
this.connectionLimiter = connectionLimiter;
this.socket = socket;
in = timeoutMonitor.createTimeoutInputStream(
socket.getInputStream(), plugin.getMaxIdleTime() * 2);
wakeLock = wakeLockManager.createWakeLock("BluetoothConnection");
wakeLock.acquire();
String address = socket.getRemoteDevice().getAddress();
if (isValidBluetoothAddress(address)) remote.put(PROP_ADDRESS, address);
}
@Override
protected InputStream getInputStream() throws IOException {
return socket.getInputStream();
protected InputStream getInputStream() {
return in;
}
@Override
@@ -44,8 +55,10 @@ class AndroidBluetoothTransportConnection
protected void closeConnection(boolean exception) throws IOException {
try {
socket.close();
in.close();
} finally {
connectionManager.connectionClosed(this);
wakeLock.release();
connectionLimiter.connectionClosed(this);
}
}
}
@@ -1,23 +1,30 @@
package org.briarproject.bramble.plugin.tcp;
import android.content.Context;
import android.annotation.TargetApi;
import android.app.Application;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import org.briarproject.bramble.PoliteExecutor;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
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 java.io.IOException;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.Executor;
@@ -28,14 +35,22 @@ import javax.net.SocketFactory;
import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Context.WIFI_SERVICE;
import static android.net.ConnectivityManager.TYPE_WIFI;
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;
@NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
class AndroidLanTcpPlugin extends LanTcpPlugin {
private static final Logger LOG =
getLogger(AndroidLanTcpPlugin.class.getName());
@@ -47,20 +62,22 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
private volatile SocketFactory socketFactory;
AndroidLanTcpPlugin(Executor ioExecutor, Context appContext,
Backoff backoff, PluginCallback callback, int maxLatency,
int maxIdleTime, int connectionTimeout) {
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime,
connectionTimeout);
AndroidLanTcpPlugin(Executor ioExecutor,
Executor wakefulIoExecutor,
Application app,
Backoff backoff,
PluginCallback callback,
int maxLatency,
int maxIdleTime,
int connectionTimeout) {
super(ioExecutor, wakefulIoExecutor, backoff, callback, maxLatency,
maxIdleTime, connectionTimeout);
// Don't execute more than one connection status check at a time
connectionStatusExecutor =
new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1);
ConnectivityManager connectivityManager = (ConnectivityManager)
appContext.getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager == null) throw new AssertionError();
this.connectivityManager = connectivityManager;
wifiManager = (WifiManager) appContext.getApplicationContext()
.getSystemService(WIFI_SERVICE);
connectivityManager = (ConnectivityManager)
requireNonNull(app.getSystemService(CONNECTIVITY_SERVICE));
wifiManager = (WifiManager) app.getSystemService(WIFI_SERVICE);
socketFactory = SocketFactory.getDefault();
}
@@ -68,37 +85,137 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
public void start() {
if (used.getAndSet(true)) throw new IllegalStateException();
initialisePortProperty();
running = true;
Settings settings = callback.getSettings();
state.setStarted(settings.getBoolean(PREF_PLUGIN_ENABLE,
DEFAULT_PREF_PLUGIN_ENABLE));
updateConnectionStatus();
}
@Override
public void stop() {
running = false;
tryToClose(socket);
}
@Override
protected Socket createSocket() throws IOException {
return socketFactory.createSocket();
}
@Override
protected List<InetAddress> getUsableLocalInetAddresses() {
// If the device doesn't have wifi, don't open any sockets
if (wifiManager == null) return emptyList();
protected List<InetAddress> getUsableLocalInetAddresses(boolean ipv4) {
InetAddress addr = getWifiAddress(ipv4);
return addr == null ? emptyList() : singletonList(addr);
}
@Nullable
private InetAddress getWifiAddress(boolean ipv4) {
Pair<InetAddress, Boolean> wifi = getWifiIpv4Address();
if (ipv4) return wifi == null ? null : wifi.getFirst();
// 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;
}
// Use the wifi IPv4 address to determine which interface's IPv6
// address we should return (if the interface has a suitable address)
return getIpv6AddressForInterface(wifi.getFirst());
}
/**
* Returns a {@link Pair} where the first element is the IPv4 address of
* the wifi interface and the second element is true if this device is
* providing an access point, or false if this device is a client. Returns
* null if this device isn't connected to wifi as an access point or client.
*/
@Nullable
private Pair<InetAddress, Boolean> getWifiIpv4Address() {
if (wifiManager == null) return null;
// If we're connected to a wifi network, return its address
WifiInfo info = wifiManager.getConnectionInfo();
if (info != null && info.getIpAddress() != 0) {
return singletonList(intToInetAddress(info.getIpAddress()));
return new Pair<>(intToInetAddress(info.getIpAddress()), false);
}
// If we're running an access point, return its address
for (InetAddress addr : getLocalInetAddresses()) {
if (addr.equals(WIFI_AP_ADDRESS)) return singletonList(addr);
if (addr.equals(WIFI_DIRECT_AP_ADDRESS)) return singletonList(addr);
List<InterfaceAddress> ifAddrs = getLocalInterfaceAddresses();
// If we're providing a normal access point, return its address
for (InterfaceAddress ifAddr : ifAddrs) {
if (isAndroidWifiApAddress(ifAddr)) {
return new Pair<>(ifAddr.getAddress(), true);
}
}
// If we're providing a wifi direct access point, return its address
for (InterfaceAddress ifAddr : ifAddrs) {
if (isAndroidWifiDirectApAddress(ifAddr)) {
return new Pair<>(ifAddr.getAddress(), true);
}
}
// Not connected to wifi
return null;
}
/**
* Returns true if the given address belongs to a network provided by an
* Android access point (including the access point's own address).
* <p>
* The access point's address is usually 192.168.43.1, but at least one
* device (Honor 8A) may use other addresses in the range 192.168.43.0/24.
*/
private boolean isAndroidWifiApAddress(InterfaceAddress ifAddr) {
if (ifAddr.getNetworkPrefixLength() != 24) return false;
byte[] ip = ifAddr.getAddress().getAddress();
return ip.length == 4
&& ip[0] == (byte) 192
&& ip[1] == (byte) 168
&& ip[2] == (byte) 43;
}
/**
* Returns true if the given address belongs to a network provided by an
* Android wifi direct legacy mode access point (including the access
* point's own address).
*/
private boolean isAndroidWifiDirectApAddress(InterfaceAddress ifAddr) {
if (ifAddr.getNetworkPrefixLength() != 24) return false;
byte[] ip = ifAddr.getAddress().getAddress();
return ip.length == 4
&& ip[0] == (byte) 192
&& ip[1] == (byte) 168
&& ip[2] == (byte) 49;
}
/**
* 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() {
for (Network net : connectivityManager.getAllNetworks()) {
NetworkCapabilities caps =
connectivityManager.getNetworkCapabilities(net);
if (caps == null || !caps.hasTransport(TRANSPORT_WIFI)) continue;
LinkProperties props = connectivityManager.getLinkProperties(net);
if (props == null) continue;
for (LinkAddress linkAddress : props.getLinkAddresses()) {
InetAddress addr = linkAddress.getAddress();
if (isIpv6LinkLocalAddress(addr)) return addr;
}
}
return null;
}
/**
* Returns a link-local IPv6 address for the interface with the given IPv4
* address, or null if the interface doesn't have a suitable address.
*/
@Nullable
private InetAddress getIpv6AddressForInterface(InetAddress ipv4) {
try {
NetworkInterface iface = NetworkInterface.getByInetAddress(ipv4);
if (iface == null) return null;
for (InetAddress addr : list(iface.getInetAddresses())) {
if (isIpv6LinkLocalAddress(addr)) return addr;
}
// No suitable address
return null;
} catch (SocketException e) {
logException(LOG, WARNING, e);
return null;
}
// No suitable addresses
return emptyList();
}
private InetAddress intToInetAddress(int ip) {
@@ -120,41 +237,71 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
private SocketFactory getSocketFactory() {
if (SDK_INT < 21) return SocketFactory.getDefault();
for (Network net : connectivityManager.getAllNetworks()) {
NetworkInfo info = connectivityManager.getNetworkInfo(net);
if (info != null && info.getType() == TYPE_WIFI)
NetworkCapabilities caps =
connectivityManager.getNetworkCapabilities(net);
if (caps != null && caps.hasTransport(TRANSPORT_WIFI)) {
return net.getSocketFactory();
}
}
LOG.warning("Could not find suitable socket factory");
return SocketFactory.getDefault();
}
@Override
public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof NetworkStatusEvent) updateConnectionStatus();
}
private void updateConnectionStatus() {
connectionStatusExecutor.execute(() -> {
if (!running) return;
List<InetAddress> addrs = getUsableLocalInetAddresses();
if (addrs.contains(WIFI_AP_ADDRESS)
|| addrs.contains(WIFI_DIRECT_AP_ADDRESS)) {
State s = getState();
if (s != ACTIVE && s != INACTIVE) return;
Pair<InetAddress, Boolean> wifi = getPreferredWifiAddress();
if (wifi == null) {
LOG.info("Not connected to wifi");
socketFactory = SocketFactory.getDefault();
// Server sockets may not have been closed automatically when
// interface was taken down. If any sockets are open, closing
// them here will cause the sockets to be cleared and the state
// to be updated in acceptContactConnections()
if (s == ACTIVE) {
LOG.info("Closing server sockets");
tryToClose(state.getServerSocket(true), LOG, WARNING);
tryToClose(state.getServerSocket(false), LOG, WARNING);
}
} else if (wifi.getSecond()) {
LOG.info("Providing wifi hotspot");
// There's no corresponding Network object and thus no way
// to get a suitable socket factory, so we won't be able to
// make outgoing connections on API 21+ if another network
// has internet access
socketFactory = SocketFactory.getDefault();
if (socket == null || socket.isClosed()) bind();
} else if (addrs.isEmpty()) {
LOG.info("Not connected to wifi");
socketFactory = SocketFactory.getDefault();
tryToClose(socket);
bind();
} else {
LOG.info("Connected to wifi");
socketFactory = getSocketFactory();
if (socket == null || socket.isClosed()) bind();
bind();
}
});
}
/**
* Returns a {@link Pair} where the first element is an IP address (IPv4 if
* available, otherwise IPv6) of the wifi interface and the second element
* is true if this device is providing an access point, or false if this
* device is a client. Returns null if this device isn't connected to wifi
* as an access point or client.
*/
@Nullable
private Pair<InetAddress, Boolean> getPreferredWifiAddress() {
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) {
InetAddress ipv6 = getWifiClientIpv6Address();
if (ipv6 != null) return new Pair<>(ipv6, false);
}
return wifi;
}
}
@@ -1,8 +1,9 @@
package org.briarproject.bramble.plugin.tcp;
import android.content.Context;
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;
@@ -10,10 +11,12 @@ import org.briarproject.bramble.api.plugin.PluginCallback;
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 java.util.concurrent.Executor;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
@@ -28,17 +31,22 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private static final int MAX_POLLING_INTERVAL = 600_000; // 10 mins
private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor;
private final Executor ioExecutor, wakefulIoExecutor;
private final EventBus eventBus;
private final BackoffFactory backoffFactory;
private final Context appContext;
private final Application app;
public AndroidLanTcpPluginFactory(Executor ioExecutor, EventBus eventBus,
BackoffFactory backoffFactory, Context appContext) {
@Inject
public AndroidLanTcpPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor,
EventBus eventBus,
BackoffFactory backoffFactory,
Application app) {
this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor;
this.eventBus = eventBus;
this.backoffFactory = backoffFactory;
this.appContext = appContext;
this.app = app;
}
@Override
@@ -56,8 +64,8 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor,
appContext, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME,
CONNECTION_TIMEOUT);
wakefulIoExecutor, app, backoff, callback,
MAX_LATENCY, MAX_IDLE_TIME, CONNECTION_TIMEOUT);
eventBus.addListener(plugin);
return plugin;
}
@@ -1,10 +1,9 @@
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.app.Application;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.PowerManager;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager;
@@ -12,48 +11,76 @@ 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.RenewableWakeLock;
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.concurrent.ScheduledExecutorService;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.net.SocketFactory;
import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.POWER_SERVICE;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.concurrent.TimeUnit.MINUTES;
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 final Context appContext;
private final RenewableWakeLock wakeLock;
private static final List<String> LIBRARY_ARCHITECTURES =
asList("armeabi-v7a", "arm64-v8a", "x86", "x86_64");
AndroidTorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
Context appContext, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, ResourceProvider resourceProvider,
private static final String TOR_LIB_NAME = "libtor.so";
private static final String OBFS4_LIB_NAME = "libobfs4proxy.so";
private static final Logger LOG =
getLogger(AndroidTorPlugin.class.getName());
private final Application app;
private final AndroidWakeLock wakeLock;
private final File torLib, obfs4Lib;
AndroidTorPlugin(Executor ioExecutor,
Executor wakefulIoExecutor,
Application app,
NetworkManager networkManager,
LocationUtils locationUtils,
SocketFactory torSocketFactory,
Clock clock,
ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
BatteryManager batteryManager,
AndroidWakeLockManager wakeLockManager,
Backoff backoff,
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, torRendezvousCrypto, callback, architecture, maxLatency, maxIdleTime,
appContext.getDir("tor", MODE_PRIVATE));
this.appContext = appContext;
PowerManager pm = (PowerManager)
appContext.getSystemService(POWER_SERVICE);
if (pm == null) throw new AssertionError();
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
getWakeLockTag(), 1, MINUTES);
PluginCallback callback,
String architecture,
int maxLatency,
int maxIdleTime,
File torDirectory) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture, maxLatency,
maxIdleTime, torDirectory);
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);
}
@Override
@@ -64,8 +91,8 @@ class AndroidTorPlugin extends TorPlugin {
@Override
protected long getLastUpdateTime() {
try {
PackageManager pm = appContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0);
PackageManager pm = app.getPackageManager();
PackageInfo pi = pm.getPackageInfo(app.getPackageName(), 0);
return pi.lastUpdateTime;
} catch (NameNotFoundException e) {
throw new AssertionError(e);
@@ -74,7 +101,6 @@ class AndroidTorPlugin extends TorPlugin {
@Override
protected void enableNetwork(boolean enable) throws IOException {
if (!running) return;
if (enable) wakeLock.acquire();
super.enableNetwork(enable);
if (!enable) wakeLock.release();
@@ -86,16 +112,111 @@ class AndroidTorPlugin extends TorPlugin {
wakeLock.release();
}
private String getWakeLockTag() {
PackageManager pm = appContext.getPackageManager();
for (PackageInfo info : pm.getInstalledPackages(0)) {
String name = info.packageName.toLowerCase();
if (name.startsWith("com.huawei.powergenie")) {
return "LocationManagerService";
} else if (name.startsWith("com.evenwell.powermonitor")) {
return "AudioIn";
@Override
protected File getTorExecutableFile() {
return torLib.exists() ? torLib : super.getTorExecutableFile();
}
@Override
protected File getObfs4ExecutableFile() {
return obfs4Lib.exists() ? obfs4Lib : super.getObfs4ExecutableFile();
}
@Override
protected void installTorExecutable() throws IOException {
File extracted = super.getTorExecutableFile();
if (torLib.exists()) {
// If an older version left behind a Tor binary, delete it
if (extracted.exists()) {
if (extracted.delete()) LOG.info("Deleted Tor binary");
else LOG.info("Failed to delete Tor binary");
}
} else if (SDK_INT < 29) {
// The binary wasn't extracted at install time. Try to extract it
extractLibraryFromApk(TOR_LIB_NAME, extracted);
} else {
// No point extracting the binary, we won't be allowed to execute it
throw new FileNotFoundException(torLib.getAbsolutePath());
}
}
return getClass().getSimpleName();
@Override
protected void installObfs4Executable() throws IOException {
File extracted = super.getObfs4ExecutableFile();
if (obfs4Lib.exists()) {
// If an older version left behind an obfs4 binary, delete it
if (extracted.exists()) {
if (extracted.delete()) LOG.info("Deleted obfs4 binary");
else LOG.info("Failed to delete obfs4 binary");
}
} else if (SDK_INT < 29) {
// The binary wasn't extracted at install time. Try to extract it
extractLibraryFromApk(OBFS4_LIB_NAME, extracted);
} else {
// No point extracting the binary, we won't be allowed to execute it
throw new FileNotFoundException(obfs4Lib.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;
}
}
@@ -1,28 +1,33 @@
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.app.Application;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.event.EventBus;
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.TorConstants;
import org.briarproject.bramble.api.plugin.TorDirectory;
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.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.bramble.util.AndroidUtils;
import java.io.File;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import javax.net.SocketFactory;
@Immutable
@@ -38,9 +43,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final Context appContext;
private final Executor ioExecutor, wakefulIoExecutor;
private final Application app;
private final NetworkManager networkManager;
private final LocationUtils locationUtils;
private final EventBus eventBus;
@@ -49,18 +53,28 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
private final ResourceProvider resourceProvider;
private final CircumventionProvider circumventionProvider;
private final BatteryManager batteryManager;
private final AndroidWakeLockManager wakeLockManager;
private final Clock clock;
private final File torDirectory;
public AndroidTorPluginFactory(Executor ioExecutor,
ScheduledExecutorService scheduler, Context appContext,
NetworkManager networkManager, LocationUtils locationUtils,
EventBus eventBus, SocketFactory torSocketFactory,
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
@Inject
public AndroidTorPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor,
Application app,
NetworkManager networkManager,
LocationUtils locationUtils,
EventBus eventBus,
SocketFactory torSocketFactory,
BackoffFactory backoffFactory,
ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Clock clock) {
BatteryManager batteryManager,
AndroidWakeLockManager wakeLockManager,
Clock clock,
@TorDirectory File torDirectory) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.appContext = appContext;
this.wakefulIoExecutor = wakefulIoExecutor;
this.app = app;
this.networkManager = networkManager;
this.locationUtils = locationUtils;
this.eventBus = eventBus;
@@ -69,7 +83,9 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager;
this.wakeLockManager = wakeLockManager;
this.clock = clock;
this.torDirectory = torDirectory;
}
@Override
@@ -112,11 +128,12 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
appContext, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager,
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor,
wakefulIoExecutor, app, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, wakeLockManager,
backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME);
MAX_LATENCY, MAX_IDLE_TIME, torDirectory);
eventBus.addListener(plugin);
return plugin;
}
@@ -0,0 +1,18 @@
package org.briarproject.bramble.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
interface AlarmConstants {
/**
* Request code for the broadcast intent attached to the periodic alarm.
*/
int REQUEST_ALARM = 1;
/**
* Key for storing the process ID in the extras of the periodic alarm's
* intent. This allows us to ignore alarms scheduled by dead processes.
*/
String EXTRA_PID = "org.briarproject.bramble.EXTRA_PID";
}
@@ -0,0 +1,17 @@
package org.briarproject.bramble.system;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.briarproject.bramble.BrambleApplication;
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent intent) {
BrambleApplication app =
(BrambleApplication) ctx.getApplicationContext();
app.getBrambleAppComponent().alarmListener().onAlarm(intent);
}
}
@@ -61,12 +61,12 @@ class AndroidLocationUtils implements LocationUtils {
private String getCountryFromPhoneNetwork() {
Object o = appContext.getSystemService(TELEPHONY_SERVICE);
TelephonyManager tm = (TelephonyManager) o;
return tm.getNetworkCountryIso();
return tm == null ? "" : tm.getNetworkCountryIso();
}
private String getCountryFromSimCard() {
Object o = appContext.getSystemService(TELEPHONY_SERVICE);
TelephonyManager tm = (TelephonyManager) o;
return tm.getSimCountryIso();
return tm == null ? "" : tm.getSimCountryIso();
}
}
@@ -6,8 +6,6 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ContentResolver;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Parcel;
import android.os.StrictMode;
@@ -17,12 +15,10 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static android.content.Context.WIFI_SERVICE;
import static android.os.Build.VERSION.SDK_INT;
import static android.provider.Settings.Secure.ANDROID_ID;
@@ -52,15 +48,6 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
if (id != null) out.writeUTF(id);
Parcel parcel = Parcel.obtain();
WifiManager wm = (WifiManager) appContext.getApplicationContext()
.getSystemService(WIFI_SERVICE);
if (wm != null) {
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
if (configs != null) {
for (WifiConfiguration config : configs)
parcel.writeParcelable(config, 0);
}
}
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt != null) {
for (BluetoothDevice device : bt.getBondedDevices())
@@ -1,12 +1,17 @@
package org.briarproject.bramble.system;
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 java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import javax.inject.Singleton;
@@ -16,6 +21,23 @@ import dagger.Provides;
@Module
public class AndroidSystemModule {
private final ScheduledExecutorService scheduledExecutorService;
public AndroidSystemModule() {
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ScheduledThreadPoolExecutor.DiscardPolicy();
scheduledExecutorService = new ScheduledThreadPoolExecutor(1, policy);
}
@Provides
@Singleton
ScheduledExecutorService provideScheduledExecutorService(
LifecycleManager lifecycleManager) {
lifecycleManager.registerForShutdown(scheduledExecutorService);
return scheduledExecutorService;
}
@Provides
@Singleton
SecureRandomProvider provideSecureRandomProvider(
@@ -47,4 +69,11 @@ public class AndroidSystemModule {
ResourceProvider provideResourceProvider(AndroidResourceProvider provider) {
return provider;
}
@Provides
@Singleton
AndroidWakeLockManager provideWakeLockManager(
AndroidWakeLockManagerImpl wakeLockManager) {
return wakeLockManager;
}
}
@@ -0,0 +1,242 @@
package org.briarproject.bramble.system;
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.Application;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Process;
import android.os.SystemClock;
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 java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
import static android.app.AlarmManager.INTERVAL_FIFTEEN_MINUTES;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.content.Context.ALARM_SERVICE;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
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;
@ThreadSafe
@NotNullByDefault
class AndroidTaskScheduler implements TaskScheduler, Service, AlarmListener {
private static final Logger LOG =
getLogger(AndroidTaskScheduler.class.getName());
private static final long ALARM_MS = INTERVAL_FIFTEEN_MINUTES;
private final Application app;
private final AndroidWakeLockManager wakeLockManager;
private final ScheduledExecutorService scheduledExecutorService;
private final AlarmManager alarmManager;
private final Object lock = new Object();
@GuardedBy("lock")
private final Queue<ScheduledTask> tasks = new PriorityQueue<>();
AndroidTaskScheduler(Application app,
AndroidWakeLockManager wakeLockManager,
ScheduledExecutorService scheduledExecutorService) {
this.app = app;
this.wakeLockManager = wakeLockManager;
this.scheduledExecutorService = scheduledExecutorService;
alarmManager = (AlarmManager)
requireNonNull(app.getSystemService(ALARM_SERVICE));
}
@Override
public void startService() {
scheduleAlarm();
}
@Override
public void stopService() {
cancelAlarm();
}
@Override
public Cancellable schedule(Runnable task, Executor executor, long delay,
TimeUnit unit) {
AtomicBoolean cancelled = new AtomicBoolean(false);
return schedule(task, executor, delay, unit, cancelled);
}
@Override
public Cancellable scheduleWithFixedDelay(Runnable task, Executor executor,
long delay, long interval, TimeUnit unit) {
AtomicBoolean cancelled = new AtomicBoolean(false);
return scheduleWithFixedDelay(task, executor, delay, interval, unit,
cancelled);
}
@Override
public void onAlarm(Intent intent) {
wakeLockManager.runWakefully(() -> {
int extraPid = intent.getIntExtra(EXTRA_PID, -1);
int currentPid = Process.myPid();
if (extraPid == currentPid) {
LOG.info("Alarm");
rescheduleAlarm();
runDueTasks();
} else if (LOG.isLoggable(INFO)) {
LOG.info("Ignoring alarm with PID " + extraPid
+ ", current PID is " + currentPid);
}
}, "TaskAlarm");
}
private Cancellable schedule(Runnable task, Executor executor, long delay,
TimeUnit unit, AtomicBoolean cancelled) {
long now = SystemClock.elapsedRealtime();
long dueMillis = now + MILLISECONDS.convert(delay, unit);
Runnable wakeful = () ->
wakeLockManager.executeWakefully(task, executor, "TaskHandoff");
Future<?> check = scheduleCheckForDueTasks(delay, unit);
ScheduledTask s = new ScheduledTask(wakeful, dueMillis, check,
cancelled);
synchronized (lock) {
tasks.add(s);
}
return s;
}
private Cancellable scheduleWithFixedDelay(Runnable task, Executor executor,
long delay, long interval, TimeUnit unit, AtomicBoolean cancelled) {
// All executions of this periodic task share a cancelled flag
Runnable wrapped = () -> {
task.run();
scheduleWithFixedDelay(task, executor, interval, interval, unit,
cancelled);
};
return schedule(wrapped, executor, delay, unit, cancelled);
}
private Future<?> scheduleCheckForDueTasks(long delay, TimeUnit unit) {
Runnable wakeful = () -> wakeLockManager.runWakefully(
this::runDueTasks, "TaskScheduler");
return scheduledExecutorService.schedule(wakeful, delay, unit);
}
@Wakeful
private void runDueTasks() {
long now = SystemClock.elapsedRealtime();
List<ScheduledTask> due = new ArrayList<>();
synchronized (lock) {
while (true) {
ScheduledTask s = tasks.peek();
if (s == null || s.dueMillis > now) break;
due.add(tasks.remove());
}
}
if (LOG.isLoggable(INFO)) {
LOG.info("Running " + due.size() + " due tasks");
}
for (ScheduledTask s : due) {
if (LOG.isLoggable(INFO)) {
LOG.info("Task is " + (now - s.dueMillis) + " ms overdue");
}
s.run();
}
}
private void scheduleAlarm() {
if (SDK_INT >= 23) scheduleIdleAlarm();
else scheduleInexactRepeatingAlarm();
}
private void rescheduleAlarm() {
// If SDK_INT < 23 the alarm repeats automatically
if (SDK_INT >= 23) scheduleIdleAlarm();
}
private void cancelAlarm() {
alarmManager.cancel(getAlarmPendingIntent());
}
private void scheduleInexactRepeatingAlarm() {
alarmManager.setInexactRepeating(ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + ALARM_MS, ALARM_MS,
getAlarmPendingIntent());
}
@TargetApi(23)
private void scheduleIdleAlarm() {
alarmManager.setAndAllowWhileIdle(ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + ALARM_MS,
getAlarmPendingIntent());
}
private PendingIntent getAlarmPendingIntent() {
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);
}
private class ScheduledTask
implements Runnable, Cancellable, Comparable<ScheduledTask> {
private final Runnable task;
private final long dueMillis;
private final Future<?> check;
private final AtomicBoolean cancelled;
public ScheduledTask(Runnable task, long dueMillis,
Future<?> check, AtomicBoolean cancelled) {
this.task = task;
this.dueMillis = dueMillis;
this.check = check;
this.cancelled = cancelled;
}
@Override
public void run() {
if (!cancelled.get()) task.run();
}
@Override
public void cancel() {
// Cancel any future executions of this task
cancelled.set(true);
// Cancel the scheduled check for due tasks
check.cancel(false);
// Remove the task from the queue
synchronized (lock) {
tasks.remove(this);
}
}
@Override
public int compareTo(ScheduledTask s) {
//noinspection UseCompareMethod
if (dueMillis < s.dueMillis) return -1;
if (dueMillis > s.dueMillis) return 1;
return 0;
}
}
}
@@ -0,0 +1,49 @@
package org.briarproject.bramble.system;
import android.app.Application;
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;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AndroidTaskSchedulerModule {
public static class EagerSingletons {
@Inject
AndroidTaskScheduler scheduler;
}
@Provides
@Singleton
AndroidTaskScheduler provideAndroidTaskScheduler(
LifecycleManager lifecycleManager, Application app,
AndroidWakeLockManager wakeLockManager,
ScheduledExecutorService scheduledExecutorService) {
AndroidTaskScheduler scheduler = new AndroidTaskScheduler(app,
wakeLockManager, scheduledExecutorService);
lifecycleManager.registerService(scheduler);
return scheduler;
}
@Provides
@Singleton
AlarmListener provideAlarmListener(AndroidTaskScheduler scheduler) {
return scheduler;
}
@Provides
@Singleton
TaskScheduler provideTaskScheduler(AndroidTaskScheduler scheduler) {
return scheduler;
}
}
@@ -0,0 +1,74 @@
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");
}
}
}
}
}
@@ -0,0 +1,125 @@
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;
}
}
}
@@ -0,0 +1,23 @@
package org.briarproject.bramble.system;
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;
import dagger.Module;
import dagger.Provides;
@Module
public
class AndroidWakefulIoExecutorModule {
@Provides
@WakefulIoExecutor
Executor provideWakefulIoExecutor(@IoExecutor Executor ioExecutor,
AndroidWakeLockManager wakeLockManager) {
return r -> wakeLockManager.executeWakefully(r, ioExecutor,
"WakefulIoExecutor");
}
}
@@ -0,0 +1,130 @@
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");
}
}
}
}
@@ -0,0 +1,22 @@
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();
}
@@ -31,6 +31,7 @@ public class AndroidUtils {
private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
private static final String STORED_REPORTS = "dev-reports";
private static final String STORED_LOGCAT = "dev-logcat";
public static Collection<String> getSupportedArchitectures() {
List<String> abis = new ArrayList<>();
@@ -107,14 +108,14 @@ public class AndroidUtils {
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
}
public static File getLogcatFile(Context ctx) {
return new File(ctx.getFilesDir(), STORED_LOGCAT);
}
/**
* Returns an array of supported content types for image attachments.
* GIFs can't be compressed on API < 24 so they're not supported.
* <p>
* TODO: Remove this restriction when large message support is added
*/
public static String[] getSupportedImageContentTypes() {
if (SDK_INT < 24) return new String[] {"image/jpeg", "image/png"};
else return new String[] {"image/jpeg", "image/png", "image/gif"};
return new String[] {"image/jpeg", "image/png", "image/gif"};
}
}
@@ -1,100 +0,0 @@
package org.briarproject.bramble.util;
import android.os.PowerManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
@ThreadSafe
@NotNullByDefault
public class RenewableWakeLock {
private static final Logger LOG =
Logger.getLogger(RenewableWakeLock.class.getName());
/**
* Automatically release the lock this many milliseconds after it's due
* to have been replaced and released.
*/
private static final int SAFETY_MARGIN_MS = 10_000;
private final PowerManager powerManager;
private final ScheduledExecutorService scheduler;
private final int levelAndFlags;
private final String tag;
private final long durationMs;
private final Runnable renewTask;
private final Object lock = new Object();
@Nullable
private PowerManager.WakeLock wakeLock; // Locking: lock
@Nullable
private ScheduledFuture future; // Locking: lock
public RenewableWakeLock(PowerManager powerManager,
ScheduledExecutorService scheduler, int levelAndFlags, String tag,
long duration, TimeUnit timeUnit) {
this.powerManager = powerManager;
this.scheduler = scheduler;
this.levelAndFlags = levelAndFlags;
this.tag = tag;
durationMs = MILLISECONDS.convert(duration, timeUnit);
renewTask = this::renew;
}
public void acquire() {
if (LOG.isLoggable(INFO)) LOG.info("Acquiring wake lock " + tag);
synchronized (lock) {
if (wakeLock != null) {
LOG.info("Already acquired");
return;
}
wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
wakeLock.setReferenceCounted(false);
wakeLock.acquire(durationMs + SAFETY_MARGIN_MS);
future = scheduler.schedule(renewTask, durationMs, MILLISECONDS);
}
}
private void renew() {
if (LOG.isLoggable(INFO)) LOG.info("Renewing wake lock " + tag);
synchronized (lock) {
if (wakeLock == null) {
LOG.info("Already released");
return;
}
PowerManager.WakeLock oldWakeLock = wakeLock;
wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
wakeLock.setReferenceCounted(false);
wakeLock.acquire(durationMs + SAFETY_MARGIN_MS);
oldWakeLock.release();
future = scheduler.schedule(renewTask, durationMs, MILLISECONDS);
}
}
public void release() {
if (LOG.isLoggable(INFO)) LOG.info("Releasing wake lock " + tag);
synchronized (lock) {
if (wakeLock == null) {
LOG.info("Already released");
return;
}
if (future == null) throw new AssertionError();
future.cancel(false);
future = null;
wakeLock.release();
wakeLock = null;
}
}
}
+56 -49
View File
@@ -1,33 +1,36 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.tools.analytics-library:protos:26.5.1:protos-26.5.1.jar:8dde1130725461fe827f2a343d353f2b51e8870661fc860d7d5ebddb097ead4e',
'com.android.tools.analytics-library:shared:26.5.1:shared-26.5.1.jar:ccc2f3b00ec17b11401610ba68553544fc8fc517120e84439ac6eb86b875e18d',
'com.android.tools.analytics-library:tracker:26.5.1:tracker-26.5.1.jar:3a76984c0fe2e847ca7a8b35b4780ef0447a9d1666946cb8e60466318e0ab5ae',
'com.android.tools.build:aapt2-proto:0.4.0:aapt2-proto-0.4.0.jar:fac0435e08898f89eeeb9ca236bea707155ff816c12205ced285ad53604133ca',
'com.android.tools.build:apksig:3.5.1:apksig-3.5.1.jar:1fd33e7f009a2a0da766cfeec4211a09f548034b015c289a66d75dd8a9302f4a',
'com.android.tools.build:apkzlib:3.5.1:apkzlib-3.5.1.jar:9f330167cbe973b7db407692f74f4f6453b7ffa5f2048934b06280c2ceee60fa',
'com.android.tools.build:builder-model:3.5.1:builder-model-3.5.1.jar:39ea3c82b76b6e0c9f9fa88d93e0edc1dd4a0f1dfae0ef6fbf2d451da47e5450',
'com.android.tools.build:builder-test-api:3.5.1:builder-test-api-3.5.1.jar:a1b59305584cbcaa078fdc9cfb80871012755b822dd32e8da19add6f7bbcb762',
'com.android.tools.build:builder:3.5.1:builder-3.5.1.jar:e3a8d382434c5f60990730c4719fc814e85a898a33a1e96c1df8d627d3c6eea6',
'com.android.tools.build:gradle-api:3.5.1:gradle-api-3.5.1.jar:be9b41859bace11998f66b04ed944f87e413f3ad6da3c4665587699da125addc',
'com.android.tools.build:manifest-merger:26.5.1:manifest-merger-26.5.1.jar:dcad9ecb967251f4d750f55a4204a2b400e8fbfe5cb930a1d0d5dbe10ae8bdfc',
'com.android.tools.ddms:ddmlib:26.5.1:ddmlib-26.5.1.jar:b081aef2a4ed3f4d47cae4cdb128469735f25a114e026d37123bf9ffdec742a8',
'com.android.tools.external.com-intellij:intellij-core:26.5.1:intellij-core-26.5.1.jar:20eced30adc124805bd93488d9cd9d3e33e6bf7b48e9fe5a703d4983f894d450',
'com.android.tools.external.com-intellij:kotlin-compiler:26.5.1:kotlin-compiler-26.5.1.jar:5aed762dd54875b77ae7018d97c05756ff0c5b9fd02ec595dd396ccd14cc22cb',
'com.android.tools.external.org-jetbrains:uast:26.5.1:uast-26.5.1.jar:4bc8653d6c0943f40fee963a149e36c6baa45683d2530968a13f5007e3c40740',
'com.android.tools.layoutlib:layoutlib-api:26.5.1:layoutlib-api-26.5.1.jar:88732f11396c427273e515d23042e35633f4fe4295528a99b866aa2adf0efd9c',
'com.android.tools.lint:lint-api:26.5.1:lint-api-26.5.1.jar:ec33fcd72bfaf70dd841e03fbfd93f109c2e575aec146067c606689c3972f0de',
'com.android.tools.lint:lint-checks:26.5.1:lint-checks-26.5.1.jar:a1b9607d484aaae7a71dcecdc76f8003d8239af226c776894a2cf63f9e6c60d7',
'com.android.tools.lint:lint-gradle-api:26.5.1:lint-gradle-api-26.5.1.jar:82453fd98a8394cc84ed995c04d2cd744abd1d6589403427ba7eef53115406f3',
'com.android.tools.lint:lint-gradle:26.5.1:lint-gradle-26.5.1.jar:59465b56cf7db77c656d5f8195d721c3d48b6bdd0502d774de335bfe4baff00b',
'com.android.tools.lint:lint:26.5.1:lint-26.5.1.jar:336e4b04ec6f8b0f25879131b7a7862d77df83a1879ee5b71be26128755f8e2e',
'com.android.tools:annotations:26.5.1:annotations-26.5.1.jar:2c43c82f8c59d8f7a61e3239e1a2dc9f69dc342ec09af9b7c9f69b25337c0b6e',
'com.android.tools:common:26.5.1:common-26.5.1.jar:eccfa54486ed54c4e3123cc42195d023bd0dd21bcd2f0e4868e8c6fc70f8ef6b',
'com.android.tools:dvlib:26.5.1:dvlib-26.5.1.jar:46f93ad498b4756e7d867d2fe38c38890a80e7407a4ae459e4a8c8d5c5aeacfe',
'com.android.tools:repository:26.5.1:repository-26.5.1.jar:2b3ee791aa4c3e8ce60498c161a27ca7228816fc630eed4d9f25f2f36a106dce',
'com.android.tools:sdk-common:26.5.1:sdk-common-26.5.1.jar:365f749676c3574676fd465177c8a492f340816db2b520d6ed114d3b6e77bea7',
'com.android.tools:sdklib:26.5.1:sdklib-26.5.1.jar:007da104afb27c8c682a1628023fe9ec438249c8d15ef0fd6624c5bb8e23b696',
'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4',
'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366',
'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9',
'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:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72',
'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127',
'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd',
'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a',
'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d',
'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358',
'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b',
'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a',
'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6',
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8',
'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714',
'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c',
'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b',
'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61',
'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d',
'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756',
'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d',
'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81',
'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1',
'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c',
'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f',
'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d',
'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c',
'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250',
'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60',
'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
@@ -35,28 +38,31 @@ dependencyVerification {
'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64',
'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.2:error_prone_annotations-2.3.2.jar:357cd6cfb067c969226c442451502aee13800a24e950fdfde77bcdb4565a668d',
'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.0.1-jre:guava-27.0.1-jre.jar:e1c814fd04492a27c38e0317eabeaa1b3e950ec8010239e400fe90ad6c9107b4',
'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
'com.google.guava:guava:28.1-jre:guava-28.1-jre.jar:30beb8b8527bd07c6e747e77f1a92122c2f29d57ce347461a4a55eb26e382da4',
'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.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
'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.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'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:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec',
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'javax.xml.bind:jaxb-api:2.2.12-b140109.1041:jaxb-api-2.2.12-b140109.1041.jar:b5e60cd8b7b5ff01ce4a74c5dd008f4fbd14ced3495d0b47b85cfedc182211f2',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122',
'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',
@@ -69,35 +75,36 @@ dependencyVerification {
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'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.11-2:obfs4proxy-android-0.0.11-2.zip:57e55cbe87aa2aac210fdbb6cd8cdeafe15f825406a08ebf77a8b787aa2c6a8a',
'org.briarproject:tor-android:0.3.5.10:tor-android-0.3.5.10.zip:edd83bf557fcff2105eaa0bdb3f607a6852ebe7360920929ae3039dd5f4774c5',
'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a:obfs4proxy-android-0.0.12-dev-40245c4a.zip:8ab05a8f8391be2cb5ab2b665c281a06d9e3a756bd0f95a40a36ca927866ea82',
'org.briarproject:tor-android:0.3.5.13:tor-android-0.3.5.13.zip:e0978db136731dae07774b722970cdae1e462fb5adc82845dd80a7e2d87f356c',
'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:2.8.1:checker-qual-2.8.1.jar:9103499008bcecd4e948da29b17864abb64304e15706444ae209d17ebe0575df',
'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
'org.glassfish.jaxb:jaxb-runtime:2.2.11:jaxb-runtime-2.2.11.jar:a874f2351cfba8e2946be3002d10c18a6da8f21b52ba2acf52f2b85d5520ed70',
'org.glassfish.jaxb:txw2:2.2.11:txw2-2.2.11.jar:272a3ccad45a4511351920cd2a8633c53cab8d5220c7a92954da5526bb5eafea',
'org.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d',
'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f',
'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jetbrains.kotlin:kotlin-reflect:1.3.50:kotlin-reflect-1.3.50.jar:64583199ea5a54aefd1bd1595288925f784226ee562d1dd279011c6075b3d7a4',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50:kotlin-stdlib-common-1.3.50.jar:8ce678e88e4ba018b66dacecf952471e4d7dfee156a8a819760a5a5ff29d323c',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50:kotlin-stdlib-jdk7-1.3.50.jar:9a026639e76212f8d57b86d55b075394c2e009f1979110751d34c05c5f75d57b',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.50:kotlin-stdlib-jdk8-1.3.50.jar:1b351fb6e09c14b55525c74c1f4cf48942eae43c348b7bc764a5e6e423d4da0c',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.50:kotlin-stdlib-1.3.50.jar:e6f05746ee0366d0b52825a090fac474dcf44082c9083bbb205bd16976488d6c',
'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-analysis:6.0:asm-analysis-6.0.jar:2f1a6387219c3a6cc4856481f221b03bd9f2408a326d416af09af5d6f608c1f4',
'org.ow2.asm:asm-commons:6.0:asm-commons-6.0.jar:f1bce5c648a96a017bdcd01fe5d59af9845297fd7b79b81c015a6fbbd9719abf',
'org.ow2.asm:asm-tree:6.0:asm-tree-6.0.jar:887998fb69727c8759e4d253f856822801e33f9fd4caa566b3ac58ee92106215',
'org.ow2.asm:asm-util:6.0:asm-util-6.0.jar:356afebdb0f870175262e5188f8709a3b17aa2a5a6a4b0340b04d4b449bca5f6',
'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:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:6.0:asm-6.0.jar:dd8971c74a4e697899a8e95caae4ea8760ea6c486dc6b97b1795e75760420461',
'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
]
}
+1 -1
View File
@@ -10,7 +10,7 @@ dependencies {
implementation "com.google.dagger:dagger:2.24"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13.1'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
@@ -6,4 +6,10 @@ package org.briarproject.bramble.api;
public interface FeatureFlags {
boolean shouldEnableImageAttachments();
boolean shouldEnableProfilePictures();
boolean shouldEnableDisappearingMessages();
boolean shouldEnableConnectViaBluetooth();
}
@@ -0,0 +1,29 @@
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 java.util.Collection;
/**
* An interface for registering a hook with the {@link CleanupManager}
* that will be called when a message's cleanup deadline is reached.
*/
@NotNullByDefault
public interface CleanupHook {
/**
* Called when the cleanup deadlines of one or more messages are reached.
* <p>
* The callee is not required to delete the messages, but the hook won't be
* called again for these messages unless another cleanup timer is set (see
* {@link DatabaseComponent#setCleanupTimerDuration(Transaction, MessageId, long)}
* and {@link DatabaseComponent#startCleanupTimer(Transaction, MessageId)}).
*/
void deleteMessages(Transaction txn, GroupId g,
Collection<MessageId> messageIds) throws DbException;
}
@@ -0,0 +1,42 @@
package org.briarproject.bramble.api.cleanup;
import org.briarproject.bramble.api.cleanup.event.CleanupTimerStartedEvent;
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;
/**
* The CleanupManager is responsible for tracking the cleanup deadlines of
* messages and passing them to their respective
* {@link CleanupHook CleanupHooks} when the deadlines are reached.
* <p>
* The CleanupManager responds to
* {@link CleanupTimerStartedEvent CleanupTimerStartedEvents} broadcast by the
* {@link DatabaseComponent}.
* <p>
* See {@link DatabaseComponent#setCleanupTimerDuration(Transaction, MessageId, long)},
* {@link DatabaseComponent#startCleanupTimer(Transaction, MessageId)},
* {@link DatabaseComponent#stopCleanupTimer(Transaction, MessageId)}.
*/
@NotNullByDefault
public interface CleanupManager {
/**
* When scheduling a cleanup task we overshoot the deadline by this many
* milliseconds to reduce the number of tasks that need to be scheduled
* when messages have cleanup deadlines that are close together.
*/
long BATCH_DELAY_MS = 1000;
/**
* Registers a hook to be called when messages are due for cleanup.
* This method should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerCleanupHook(ClientId c, int majorVersion,
CleanupHook hook);
}
@@ -0,0 +1,32 @@
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 javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a message's cleanup timer is started.
*/
@Immutable
@NotNullByDefault
public class CleanupTimerStartedEvent extends Event {
private final MessageId messageId;
private final long cleanupDeadline;
public CleanupTimerStartedEvent(MessageId messageId,
long cleanupDeadline) {
this.messageId = messageId;
this.cleanupDeadline = cleanupDeadline;
}
public MessageId getMessageId() {
return messageId;
}
public long getCleanupDeadline() {
return cleanupDeadline;
}
}
@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.data.BdfDictionary;
@@ -16,6 +17,7 @@ import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.Map;
@NotNullByDefault
@@ -50,9 +52,11 @@ public interface ClientHelper {
BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g)
throws DbException, FormatException;
Collection<MessageId> getMessageIds(Transaction txn, GroupId g,
BdfDictionary query) throws DbException, FormatException;
BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException,
FormatException;
throws DbException, FormatException;
BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m)
throws DbException, FormatException;
@@ -119,4 +123,17 @@ public interface ClientHelper {
Map<TransportId, TransportProperties> parseAndValidateTransportPropertiesMap(
BdfDictionary properties) throws FormatException;
/**
* Retrieves the contact ID from the group metadata of the given contact
* group.
*/
ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException, FormatException;
/**
* Stores the given contact ID in the group metadata of the given contact
* group.
*/
void setContactId(Transaction txn, GroupId contactGroupId, ContactId c)
throws DbException;
}
@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.client;
public interface ContactGroupConstants {
/**
* Group metadata key for associating a contact ID with a contact group.
*/
String GROUP_KEY_CONTACT_ID = "contactId";
}
@@ -1,8 +1,11 @@
package org.briarproject.bramble.api.plugin;
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;
@NotNullByDefault
@@ -0,0 +1,130 @@
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;
import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
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 java.util.Collection;
/**
* Keeps track of which contacts are currently connected by which transports.
*/
@NotNullByDefault
public interface ConnectionRegistry {
/**
* Registers an incoming connection from the given contact over the given
* transport. The connection's {@link Priority priority} can be set later
* via {@link #setPriority(ContactId, TransportId, InterruptibleConnection,
* Priority)} if a priority record is received from the contact.
* <p>
* Broadcasts {@link ConnectionOpenedEvent}. Also broadcasts
* {@link ContactConnectedEvent} if this is the only connection with the
* contact.
*/
void registerIncomingConnection(ContactId c, TransportId t,
InterruptibleConnection conn);
/**
* Registers an outgoing connection to the given contact over the given
* transport.
* <p>
* Broadcasts {@link ConnectionOpenedEvent}. Also broadcasts
* {@link ContactConnectedEvent} if this is the only connection with the
* contact.
* <p>
* If the registry has any "better" connections with the given contact, the
* given connection will be interrupted. If the registry has any "worse"
* connections with the given contact, those connections will be
* interrupted.
* <p>
* Connection A is considered "better" than connection B if both
* connections have had their priorities set, and either A's transport is
* {@link PluginConfig#getTransportPreferences() preferred} to B's, or
* they use the same transport and A has higher {@link Priority priority}
* than B.
* <p>
* For backward compatibility, connections without priorities are not
* considered better or worse than other connections.
*/
void registerOutgoingConnection(ContactId c, TransportId t,
InterruptibleConnection conn, Priority priority);
/**
* Unregisters a connection with the given contact over the given transport.
* <p>
* Broadcasts {@link ConnectionClosedEvent}. Also broadcasts
* {@link ContactDisconnectedEvent} if this is the only connection with
* the contact.
*/
void unregisterConnection(ContactId c, TransportId t,
InterruptibleConnection conn, boolean incoming, boolean exception);
/**
* Sets the {@link Priority priority} of a connection that was previously
* registered via {@link #registerIncomingConnection(ContactId, TransportId,
* InterruptibleConnection)}.
* <p>
* If the registry has any "better" connections with the given contact, the
* given connection will be interrupted. If the registry has any "worse"
* connections with the given contact, those connections will be
* interrupted.
* <p>
* Connection A is considered "better" than connection B if both
* connections have had their priorities set, and either A's transport is
* {@link PluginConfig#getTransportPreferences() preferred} to B's, or
* they use the same transport and A has higher {@link Priority priority}
* than B.
* <p>
* For backward compatibility, connections without priorities are not
* considered better or worse than other connections.
*/
void setPriority(ContactId c, TransportId t, InterruptibleConnection conn,
Priority priority);
/**
* Returns any contacts that are connected via the given transport.
*/
Collection<ContactId> getConnectedContacts(TransportId t);
/**
* Returns any contacts that are connected via the given transport or any
* {@link PluginConfig#getTransportPreferences() better} transport.
*/
Collection<ContactId> getConnectedOrBetterContacts(TransportId t);
/**
* Returns true if the given contact is connected via the given transport.
*/
boolean isConnected(ContactId c, TransportId t);
/**
* Returns true if the given contact is connected via any transport.
*/
boolean isConnected(ContactId c);
/**
* Registers a connection with the given pending contact. Broadcasts
* {@link RendezvousConnectionOpenedEvent} if this is the only connection
* with the pending contact.
*
* @return True if this is the only connection with the pending contact,
* false if it is redundant and should be closed
*/
boolean registerConnection(PendingContactId p);
/**
* Unregisters a connection with the given pending contact. Broadcasts
* {@link RendezvousConnectionClosedEvent}.
*/
void unregisterConnection(PendingContactId p, boolean success);
}
@@ -0,0 +1,19 @@
package org.briarproject.bramble.api.connection;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* A duplex sync connection that can be closed by interrupting its outgoing
* sync session.
*/
@NotNullByDefault
public interface InterruptibleConnection {
/**
* Interrupts the connection's outgoing sync session. If the underlying
* transport connection is alive and the remote peer is cooperative, this
* should result in both sync sessions ending and the connection being
* cleanly closed.
*/
void interruptOutgoingSession();
}
@@ -11,7 +11,6 @@ import org.briarproject.bramble.api.db.PendingContactExistsException;
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.identity.AuthorInfo;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -179,6 +178,11 @@ public interface ContactManager {
*/
Collection<Contact> getContacts() throws DbException;
/**
* Returns all contacts.
*/
Collection<Contact> getContacts(Transaction txn) throws DbException;
/**
* Removes a contact and all associated state.
*/
@@ -215,16 +219,6 @@ public interface ContactManager {
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
*/
AuthorInfo getAuthorInfo(AuthorId a) throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
*/
AuthorInfo getAuthorInfo(Transaction txn, AuthorId a) throws DbException;
interface ContactHook {
/**
@@ -0,0 +1,35 @@
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 javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when the alias for a contact changed.
*/
@Immutable
@NotNullByDefault
public class ContactAliasChangedEvent extends Event {
private final ContactId contactId;
@Nullable
private final String alias;
public ContactAliasChangedEvent(ContactId contactId,
@Nullable String alias) {
this.contactId = contactId;
this.alias = alias;
}
public ContactId getContactId() {
return contactId;
}
@Nullable
public String getAlias() {
return alias;
}
}
@@ -19,4 +19,10 @@ public interface StreamDecrypterFactory {
*/
StreamDecrypter createContactExchangeStreamDecrypter(InputStream in,
SecretKey headerKey);
/**
* Creates a {@link StreamDecrypter} for decrypting a log stream.
*/
StreamDecrypter createLogStreamDecrypter(InputStream in,
SecretKey headerKey);
}
@@ -17,6 +17,12 @@ public interface StreamEncrypterFactory {
* Creates a {@link StreamEncrypter} for encrypting a contact exchange
* stream.
*/
StreamEncrypter createContactExchangeStreamDecrypter(OutputStream out,
StreamEncrypter createContactExchangeStreamEncrypter(OutputStream out,
SecretKey headerKey);
/**
* Creates a {@link StreamEncrypter} for encrypting a log stream.
*/
StreamEncrypter createLogStreamEncrypter(OutputStream out,
SecretKey headerKey);
}
@@ -41,6 +41,18 @@ import javax.annotation.Nullable;
@NotNullByDefault
public interface DatabaseComponent extends TransactionManager {
/**
* Return value for {@link #getNextCleanupDeadline(Transaction)} if
* no messages are scheduled to be deleted.
*/
long NO_CLEANUP_DEADLINE = -1;
/**
* Return value for {@link #startCleanupTimer(Transaction, MessageId)}
* if the cleanup timer was not started.
*/
long TIMER_NOT_STARTED = -1;
/**
* Opens the database and returns true if the database already existed.
*
@@ -288,6 +300,16 @@ public interface DatabaseComponent extends TransactionManager {
Collection<MessageId> getMessageIds(Transaction txn, GroupId g)
throws DbException;
/**
* Returns the IDs of any delivered messages in the given group with
* metadata that matches all entries in the given query. If the query is
* empty, the IDs of all delivered messages are returned.
* <p/>
* Read-only.
*/
Collection<MessageId> getMessageIds(Transaction txn, GroupId g,
Metadata query) throws DbException;
/**
* Returns the IDs of any messages that need to be validated.
* <p/>
@@ -314,6 +336,15 @@ public interface DatabaseComponent extends TransactionManager {
Collection<MessageId> getMessagesToShare(Transaction txn)
throws DbException;
/**
* Returns the IDs of any messages of any messages that are due for
* deletion, along with their group IDs.
* <p/>
* Read-only.
*/
Map<GroupId, Collection<MessageId>> getMessagesToDelete(Transaction txn)
throws DbException;
/**
* Returns the metadata for all delivered messages in the given group.
* <p/>
@@ -395,6 +426,15 @@ public interface DatabaseComponent extends TransactionManager {
MessageStatus getMessageStatus(Transaction txn, ContactId c, MessageId m)
throws DbException;
/**
* Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be deleted, or {@link #NO_CLEANUP_DEADLINE}
* if no messages are scheduled to be deleted.
* <p/>
* Read-only.
*/
long getNextCleanupDeadline(Transaction txn) throws DbException;
/*
* Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be sent to the given contact. The returned value may
@@ -535,6 +575,13 @@ public interface DatabaseComponent extends TransactionManager {
void removeTransportKeys(Transaction txn, TransportId t, KeySetId k)
throws DbException;
/**
* Sets the cleanup timer duration for the given message. This does not
* start the message's cleanup timer.
*/
void setCleanupTimerDuration(Transaction txn, MessageId m, long duration)
throws DbException;
/**
* Marks the given contact as verified.
*/
@@ -557,6 +604,12 @@ public interface DatabaseComponent extends TransactionManager {
*/
void setMessagePermanent(Transaction txn, MessageId m) throws DbException;
/**
* Marks the given message as not shared. This method is only meant for
* testing.
*/
void setMessageNotShared(Transaction txn, MessageId m) throws DbException;
/**
* Marks the given message as shared.
*/
@@ -599,6 +652,22 @@ public interface DatabaseComponent extends TransactionManager {
void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k)
throws DbException;
/**
* Starts the cleanup timer for the given message, if a timer duration
* has been set and the timer has not already been started.
*
* @return The cleanup deadline, or {@link #TIMER_NOT_STARTED} if no
* timer duration has been set for this message or its timer has already
* been started.
*/
long startCleanupTimer(Transaction txn, MessageId m) throws DbException;
/**
* Stops the cleanup timer for the given message, if the timer has been
* started.
*/
void stopCleanupTimer(Transaction txn, MessageId m) throws DbException;
/**
* Stores the given transport keys, deleting any keys they have replaced.
*/
@@ -18,6 +18,8 @@ public interface EventBus {
/**
* Asynchronously notifies all listeners of an event. Listeners are
* notified on the {@link EventExecutor}.
* <p>
* This method can safely be called while holding a lock.
*/
void broadcast(Event e);
}
@@ -57,6 +57,7 @@ public class Author implements Nameable {
/**
* Returns the author's name.
*/
@Override
public String getName() {
return name;
}
@@ -0,0 +1,19 @@
package org.briarproject.bramble.api.io;
import java.io.InputStream;
public interface TimeoutMonitor {
/**
* Returns an {@link InputStream} that wraps the given stream and allows
* read timeouts to be detected.
* <p>
* The returned stream must be {@link InputStream#close() closed} when it's
* no longer needed to ensure that resources held by the timeout monitor
* are released.
*
* @param timeoutMs The read timeout in milliseconds. Timeouts will be
* detected eventually but are not guaranteed to be detected immediately.
*/
InputStream createTimeoutInputStream(InputStream in, long timeoutMs);
}
@@ -5,6 +5,7 @@ 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.system.Wakeful;
import java.util.concurrent.ExecutorService;
@@ -65,6 +66,7 @@ public interface LifecycleManager {
* Opens the {@link DatabaseComponent} using the given key and starts any
* registered {@link Service Services}.
*/
@Wakeful
StartResult startServices(SecretKey dbKey);
/**
@@ -72,6 +74,7 @@ public interface LifecycleManager {
* registered {@link ExecutorService ExecutorServices}, and closes the
* {@link DatabaseComponent}.
*/
@Wakeful
void stopServices();
/**
@@ -104,6 +107,7 @@ public interface LifecycleManager {
*
* @param txn A read-write transaction
*/
@Wakeful
void onDatabaseOpened(Transaction txn) throws DbException;
}
}
@@ -1,16 +1,20 @@
package org.briarproject.bramble.api.lifecycle;
import org.briarproject.bramble.api.system.Wakeful;
public interface Service {
/**
* Starts the service. This method must not be called concurrently with
* {@link #stopService()}.
*/
@Wakeful
void startService() throws ServiceException;
/**
* Stops the service. This method must not be called concurrently with
* {@link #startService()}.
*/
@Wakeful
void stopService() throws ServiceException;
}
@@ -8,11 +8,12 @@ import javax.annotation.concurrent.Immutable;
@NotNullByDefault
public class NetworkStatus {
private final boolean connected, wifi;
private final boolean connected, wifi, ipv6Only;
public NetworkStatus(boolean connected, boolean wifi) {
public NetworkStatus(boolean connected, boolean wifi, boolean ipv6Only) {
this.connected = connected;
this.wifi = wifi;
this.ipv6Only = ipv6Only;
}
public boolean isConnected() {
@@ -22,4 +23,8 @@ public class NetworkStatus {
public boolean isWifi() {
return wifi;
}
public boolean isIpv6Only() {
return ipv6Only;
}
}
@@ -29,4 +29,12 @@ public class NullSafety {
public static void requireNull(@Nullable Object o) {
if (o != null) throw new AssertionError();
}
/**
* Stand-in for {@code Objects.equals()}.
*/
public static boolean equals(@Nullable Object a, @Nullable Object b) {
return (a == b) || (a != null && a.equals(b));
}
}
@@ -6,8 +6,16 @@ public interface BluetoothConstants {
int UUID_BYTES = 16;
// Transport properties
String PROP_ADDRESS = "address";
String PROP_UUID = "uuid";
String PREF_BT_ENABLE = "enable";
// Local settings (not shared with contacts)
String PREF_ADDRESS_IS_REFLECTED = "addressIsReflected";
String PREF_EVER_CONNECTED = "everConnected";
// Default values for local settings
boolean DEFAULT_PREF_PLUGIN_ENABLE = false;
boolean DEFAULT_PREF_ADDRESS_IS_REFLECTED = false;
boolean DEFAULT_PREF_EVER_CONNECTED = false;
}
@@ -1,67 +0,0 @@
package org.briarproject.bramble.api.plugin;
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.event.ConnectionClosedEvent;
import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
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 java.util.Collection;
/**
* Keeps track of which contacts are currently connected by which transports.
*/
@NotNullByDefault
public interface ConnectionRegistry {
/**
* Registers a connection with the given contact over the given transport.
* Broadcasts {@link ConnectionOpenedEvent}. Also broadcasts
* {@link ContactConnectedEvent} if this is the only connection with the
* contact.
*/
void registerConnection(ContactId c, TransportId t, boolean incoming);
/**
* Unregisters a connection with the given contact over the given transport.
* Broadcasts {@link ConnectionClosedEvent}. Also broadcasts
* {@link ContactDisconnectedEvent} if this is the only connection with
* the contact.
*/
void unregisterConnection(ContactId c, TransportId t, boolean incoming);
/**
* Returns any contacts that are connected via the given transport.
*/
Collection<ContactId> getConnectedContacts(TransportId t);
/**
* Returns true if the given contact is connected via the given transport.
*/
boolean isConnected(ContactId c, TransportId t);
/**
* Returns true if the given contact is connected via any transport.
*/
boolean isConnected(ContactId c);
/**
* Registers a connection with the given pending contact. Broadcasts
* {@link RendezvousConnectionOpenedEvent} if this is the only connection
* with the pending contact.
*
* @return True if this is the only connection with the pending contact,
* false if it is redundant and should be closed
*/
boolean registerConnection(PendingContactId p);
/**
* Unregisters a connection with the given pending contact. Broadcasts
* {@link RendezvousConnectionClosedEvent}.
*/
void unregisterConnection(PendingContactId p, boolean success);
}
@@ -7,7 +7,12 @@ public interface LanTcpConstants {
// Transport properties (shared with contacts)
String PROP_IP_PORTS = "ipPorts";
String PROP_PORT = "port";
String PROP_IPV6 = "ipv6";
// A local setting
// Local settings (not shared with contacts)
String PREF_LAN_IP_PORTS = "ipPorts";
String PREF_IPV6 = "ipv6";
// Default value for PREF_PLUGIN_ENABLE
boolean DEFAULT_PREF_PLUGIN_ENABLE = true;
}
@@ -3,12 +3,56 @@ package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.system.Wakeful;
import java.util.Collection;
@NotNullByDefault
public interface Plugin {
enum State {
/**
* The plugin has not finished starting or has been stopped.
*/
STARTING_STOPPING,
/**
* The plugin is disabled by settings. Use {@link #getReasonsDisabled()}
* to find out which settings are responsible.
*/
DISABLED,
/**
* The plugin is being enabled and can't yet make or receive
* connections.
*/
ENABLING,
/**
* The plugin is enabled and can make or receive connections.
*/
ACTIVE,
/**
* The plugin is enabled but can't make or receive connections
*/
INACTIVE
}
/**
* The string for the boolean preference
* to use with the {@link SettingsManager} to enable or disable the plugin.
*/
String PREF_PLUGIN_ENABLE = "enable";
/**
* Reason flag returned by {@link #getReasonsDisabled()} to indicate that
* the plugin has been disabled by the user.
*/
int REASON_USER = 1;
/**
* Returns the plugin's transport identifier.
*/
@@ -27,17 +71,28 @@ public interface Plugin {
/**
* Starts the plugin.
*/
@Wakeful
void start() throws PluginException;
/**
* Stops the plugin.
*/
@Wakeful
void stop() throws PluginException;
/**
* Returns true if the plugin is running.
* Returns the current state of the plugin.
*/
boolean isRunning();
State getState();
/**
* Returns a set of flags indicating why the plugin is
* {@link State#DISABLED disabled}, or 0 if the plugin is not disabled.
* <p>
* The flags used are plugin-specific, except the generic flag
* {@link #REASON_USER}, which may be used by any plugin.
*/
int getReasonsDisabled();
/**
* Returns true if the plugin should be polled periodically to attempt to
@@ -54,6 +109,7 @@ public interface Plugin {
* Attempts to create connections using the given transport properties,
* passing any created connections to the corresponding handlers.
*/
@Wakeful
void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties);
}
@@ -1,9 +1,15 @@
package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.event.TransportActiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings;
import java.util.Collection;
/**
* An interface through which a transport plugin interacts with the rest of
* the application.
@@ -21,6 +27,11 @@ public interface PluginCallback extends ConnectionHandler {
*/
TransportProperties getLocalProperties();
/**
* Returns the plugin's remote transport properties.
*/
Collection<TransportProperties> getRemoteProperties();
/**
* Merges the given settings with the plugin's settings
*/
@@ -32,12 +43,17 @@ public interface PluginCallback extends ConnectionHandler {
void mergeLocalProperties(TransportProperties p);
/**
* Signals that the transport is enabled.
* Informs the callback of the plugin's current state.
* <p>
* If the current state is different from the previous state, the callback
* will broadcast a {@link TransportStateEvent}. If the current state is
* {@link State#ACTIVE} and the previous state was not
* {@link State#ACTIVE}, the callback will broadcast a
* {@link TransportActiveEvent}. If the current state is not
* {@link State#ACTIVE} and the previous state was {@link State#ACTIVE},
* the callback will broadcast a {@link TransportInactiveEvent}.
* <p>
* This method can safely be called while holding a lock.
*/
void transportEnabled();
/**
* Signals that the transport is disabled.
*/
void transportDisabled();
void pluginStateChanged(State state);
}
@@ -5,6 +5,8 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@NotNullByDefault
public interface PluginConfig {
@@ -14,4 +16,11 @@ public interface PluginConfig {
Collection<SimplexPluginFactory> getSimplexFactories();
boolean shouldPoll();
/**
* Returns a map representing transport preferences. For each entry in the
* map, connections via the transports identified by the value are
* preferred to connections via the transport identified by the key.
*/
Map<TransportId, List<TransportId>> getTransportPreferences();
}
@@ -41,4 +41,17 @@ public interface PluginManager {
* Returns any duplex plugins that support rendezvous.
*/
Collection<DuplexPlugin> getRendezvousPlugins();
/**
* Enables or disables the plugin
* identified by the given {@link TransportId}.
* <p>
* Note that this applies the change asynchronously
* and there are no order guarantees.
* <p>
* If no plugin with the given {@link TransportId} is registered,
* this is a no-op.
*/
void setPluginEnabled(TransportId t, boolean enabled);
}
@@ -1,9 +1,12 @@
package org.briarproject.bramble.api.plugin;
import static java.util.concurrent.TimeUnit.DAYS;
public interface TorConstants {
TransportId ID = new TransportId("org.briarproject.bramble.tor");
// Transport properties
String PROP_ONION_V2 = "onion";
String PROP_ONION_V3 = "onion3";
@@ -13,14 +16,45 @@ public interface TorConstants {
int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds
int EXTRA_SOCKET_TIMEOUT = 30000; // Milliseconds
// Local settings (not shared with contacts)
String PREF_TOR_NETWORK = "network2";
String PREF_TOR_PORT = "port";
String PREF_TOR_MOBILE = "useMobileData";
String PREF_TOR_ONLY_WHEN_CHARGING = "onlyWhenCharging";
String HS_PRIVATE_KEY_V2 = "onionPrivKey";
String HS_PRIVATE_KEY_V3 = "onionPrivKey3";
String HS_V3_CREATED = "onionPrivKey3Created";
/**
* How long to publish a v3 hidden service before retiring the v2 service.
*/
long V3_MIGRATION_PERIOD_MS = DAYS.toMillis(180);
// Values for PREF_TOR_NETWORK
int PREF_TOR_NETWORK_AUTOMATIC = 0;
int PREF_TOR_NETWORK_WITHOUT_BRIDGES = 1;
int PREF_TOR_NETWORK_WITH_BRIDGES = 2;
// TODO: Remove when settings migration code is removed
int PREF_TOR_NETWORK_NEVER = 3;
// Default values for local settings
boolean DEFAULT_PREF_PLUGIN_ENABLE = true;
int DEFAULT_PREF_TOR_NETWORK = PREF_TOR_NETWORK_AUTOMATIC;
boolean DEFAULT_PREF_TOR_MOBILE = true;
boolean DEFAULT_PREF_TOR_ONLY_WHEN_CHARGING = false;
/**
* Reason flag returned by {@link Plugin#getReasonsDisabled()}.
*/
int REASON_BATTERY = 2;
/**
* Reason flag returned by {@link Plugin#getReasonsDisabled()}.
*/
int REASON_MOBILE_DATA = 4;
/**
* Reason flag returned by {@link Plugin#getReasonsDisabled()}.
*/
int REASON_COUNTRY_BLOCKED = 8;
}
@@ -1,5 +1,6 @@
package org.briarproject.bramble.api.system;
package org.briarproject.bramble.api.plugin;
import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@@ -11,15 +12,11 @@ import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting a scheduled executor service
* that can be used to schedule the execution of tasks.
* <p>
* The service should <b>only</b> be used for running tasks on other executors
* at scheduled times.
* No significant work should be run by the service itself!
* Annotation for injecting the {@link File directory} where the Tor plugin
* should store its state.
*/
@Qualifier
@Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface Scheduler {
public @interface TorDirectory {
}
@@ -4,4 +4,7 @@ public interface WanTcpConstants {
TransportId ID = new TransportId("org.briarproject.bramble.wan");
// Default value for PREF_PLUGIN_ENABLE
boolean DEFAULT_PREF_PLUGIN_ENABLE = false;
}
@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint;
import org.briarproject.bramble.api.system.Wakeful;
import javax.annotation.Nullable;
@@ -21,6 +22,7 @@ public interface DuplexPlugin extends Plugin {
* Attempts to create and return a connection using the given transport
* properties. Returns null if a connection cannot be created.
*/
@Wakeful
@Nullable
DuplexTransportConnection createConnection(TransportProperties p);
@@ -1,15 +0,0 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that informs the Bluetooth plugin that we have enabled the
* Bluetooth adapter.
*/
@Immutable
@NotNullByDefault
public class BluetoothEnabledEvent extends Event {
}
@@ -13,13 +13,14 @@ public class ConnectionClosedEvent extends Event {
private final ContactId contactId;
private final TransportId transportId;
private final boolean incoming;
private final boolean incoming, exception;
public ConnectionClosedEvent(ContactId contactId, TransportId transportId,
boolean incoming) {
boolean incoming, boolean exception) {
this.contactId = contactId;
this.transportId = transportId;
this.incoming = incoming;
this.exception = exception;
}
public ContactId getContactId() {
@@ -33,4 +34,8 @@ public class ConnectionClosedEvent extends Event {
public boolean isIncoming() {
return incoming;
}
public boolean isException() {
return exception;
}
}
@@ -1,15 +0,0 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that asks the Bluetooth plugin to disable the Bluetooth adapter if
* we previously enabled it.
*/
@Immutable
@NotNullByDefault
public class DisableBluetoothEvent extends Event {
}
@@ -1,14 +0,0 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that asks the Bluetooth plugin to enable the Bluetooth adapter.
*/
@Immutable
@NotNullByDefault
public class EnableBluetoothEvent extends Event {
}
@@ -2,20 +2,22 @@ package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a transport is enabled.
* An event that is broadcast when a plugin enters the {@link State#ACTIVE}
* state.
*/
@Immutable
@NotNullByDefault
public class TransportEnabledEvent extends Event {
public class TransportActiveEvent extends Event {
private final TransportId transportId;
public TransportEnabledEvent(TransportId transportId) {
public TransportActiveEvent(TransportId transportId) {
this.transportId = transportId;
}
@@ -2,20 +2,22 @@ package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a transport is disabled.
* An event that is broadcast when a plugin leaves the {@link State#ACTIVE}
* state.
*/
@Immutable
@NotNullByDefault
public class TransportDisabledEvent extends Event {
public class TransportInactiveEvent extends Event {
private final TransportId transportId;
public TransportDisabledEvent(TransportId transportId) {
public TransportInactiveEvent(TransportId transportId) {
this.transportId = transportId;
}
@@ -0,0 +1,32 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when the {@link State state} of a plugin changes.
*/
@Immutable
@NotNullByDefault
public class TransportStateEvent extends Event {
private final TransportId transportId;
private final State state;
public TransportStateEvent(TransportId transportId, State state) {
this.transportId = transportId;
this.state = state;
}
public TransportId getTransportId() {
return transportId;
}
public State getState() {
return state;
}
}
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.system.Wakeful;
import javax.annotation.Nullable;
@@ -18,6 +19,7 @@ public interface SimplexPlugin extends Plugin {
* Attempts to create and return a reader for the given transport
* properties. Returns null if a reader cannot be created.
*/
@Wakeful
@Nullable
TransportConnectionReader createReader(TransportProperties p);
@@ -25,6 +27,7 @@ public interface SimplexPlugin extends Plugin {
* Attempts to create and return a writer for the given transport
* properties. Returns null if a writer cannot be created.
*/
@Wakeful
@Nullable
TransportConnectionWriter createWriter(TransportProperties p);
}
@@ -12,6 +12,11 @@ public interface TransportPropertyConstants {
*/
int MAX_PROPERTY_LENGTH = 100;
/**
* Prefix for keys that represent reflected properties.
*/
String REFLECTED_PROPERTY_PREFIX = "u:";
/**
* Message metadata key for the transport ID of a local or remote update,
* as a BDF string.
@@ -0,0 +1,27 @@
package org.briarproject.bramble.api.properties.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when {@link TransportProperties} are received
* from a contact.
*/
@Immutable
@NotNullByDefault
public class RemoteTransportPropertiesUpdatedEvent extends Event {
private final TransportId transportId;
public RemoteTransportPropertiesUpdatedEvent(TransportId transportId) {
this.transportId = transportId;
}
public TransportId getTransportId() {
return transportId;
}
}
@@ -13,4 +13,6 @@ public interface DevConfig {
String getDevOnionAddress();
File getReportDir();
File getLogcatFile();
}
@@ -23,6 +23,8 @@ public interface DevReporter {
/**
* Sends any reports previously stored on disk.
*
* @return The number of reports that were sent.
*/
void sendReports();
int sendReports();
}
@@ -21,5 +21,6 @@ public interface ReportingConstants {
* Hidden service address for reporting crashes and feedback to the
* developers.
*/
String DEV_ONION_ADDRESS = "cwqmubyvnig3wag3.onion";
String DEV_ONION_ADDRESS =
"b2nkt5doeamvdmjzfz7g42hk5vdtlnktlgzhel2bgjcc4v4jhnx2qrqd.onion";
}
@@ -0,0 +1,23 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* A record containing a nonce for choosing between redundant sessions.
*/
@Immutable
@NotNullByDefault
public class Priority {
private final byte[] nonce;
public Priority(byte[] nonce) {
this.nonce = nonce;
}
public byte[] getNonce() {
return nonce;
}
}

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