Compare commits

..

60 Commits

Author SHA1 Message Date
akwizgran
b02d89967e Use /dev/urandom for tests. 2018-08-20 16:54:46 +01:00
akwizgran
65ce049737 Enable logging to console for briar-core tests. 2018-08-20 15:53:13 +01:00
akwizgran
335c360ef8 Ignore IntroductionIntegrationTest. 2018-08-20 15:35:15 +01:00
akwizgran
fc26aaa168 Run only briar-core tests. 2018-08-20 15:23:35 +01:00
akwizgran
88224793c1 Fix cache paths. 2018-08-20 12:24:28 +01:00
akwizgran
0bf74f6a69 Environment var isn't available when creating cache. 2018-08-20 12:20:18 +01:00
akwizgran
4286621b02 Specify cache key. 2018-08-20 12:12:33 +01:00
akwizgran
b3e3b970ab List Gradle user directory. 2018-08-20 12:11:13 +01:00
akwizgran
ef10a08165 List cached directories. 2018-08-20 12:07:56 +01:00
akwizgran
094e1f8b65 List wrapper dists directory. 2018-08-20 12:06:46 +01:00
akwizgran
8b58bdb289 Remove stop command, use cache path. 2018-08-20 12:05:06 +01:00
akwizgran
7f61061f15 Stop daemon, just run Animal Sniffer. 2018-08-20 11:59:16 +01:00
akwizgran
cd127670bb Just clean, don't run tests. 2018-08-20 11:56:46 +01:00
akwizgran
a9b412be40 Slightly less minimal .gitlab-ci.yml 2018-08-20 11:56:45 +01:00
akwizgran
413360db09 Minimal .gitlab-ci.yml for debugging. 2018-08-20 11:56:45 +01:00
akwizgran
e5112ae9ee Merge branch 'gradle-witness' into 'master'
Move gradle witness dependency verification into dedicated files

See merge request briar/briar!892
2018-08-15 15:21:56 +00:00
Torsten Grote
f399ce9290 Use gradle wrapper for updating dependency pinning instead of local gradle 2018-08-15 12:01:13 -03:00
Torsten Grote
30e036c672 Move gradle witness dependency verification into dedicated files
This also adds a script for makes upgrading dependency checksums so much easier
2018-08-14 18:01:34 -03:00
akwizgran
2896700e50 Merge branch 'preference-switches' into 'master'
Replace CheckBoxPreference with the more standard SwitchPreference

See merge request briar/briar!891
2018-08-14 10:21:12 +00:00
akwizgran
987baba3bc Update settings.xml 2018-08-14 10:00:36 +00:00
akwizgran
03191ff08f Merge branch 'master' into 'preference-switches'
# Conflicts:
#   briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
2018-08-14 09:59:22 +00:00
akwizgran
42031631dd Merge branch '1247-pin-lock' into 'master'
Screen Lock Feature

See merge request briar/briar!870
2018-08-14 09:28:04 +00:00
Torsten Grote
64e30844b8 Screen Lock: Remember when keyguard was shown (for Android 6)
Also automatically unlock if device screenlock was removed.
2018-08-13 14:36:35 -03:00
Torsten Grote
30a070dd13 Replace CheckBoxPreference witht he more standard SwitchPreference 2018-08-13 13:57:28 -03:00
Torsten Grote
4f18303a1f Merge branch 'remove-unused-constants' into 'master'
Remove unused constants

See merge request briar/briar!889
2018-08-10 17:30:16 +00:00
Torsten Grote
5c500fb740 Merge branch 'back-facing-camera-not-required' into 'master'
Make back-facing camera optional in manifest

See merge request briar/briar!888
2018-08-10 16:30:29 +00:00
Torsten Grote
4d63272c04 Prevent activity loops when pressing back button while unlocking
This solution even works when "don't keep activities" is active
2018-08-10 13:28:43 -03:00
akwizgran
16b09b9380 Make back-facing camera optional in manifest. 2018-08-10 16:31:35 +01:00
akwizgran
a1599df712 Remove unused constants. 2018-08-10 15:04:08 +01:00
Torsten Grote
afa3c3a70e Screen Lock: Show verbose unlock message for older APIs 2018-08-10 07:44:10 -03:00
Torsten Grote
0f37a43415 Screen Lock: More changes due to code review 2018-08-10 07:44:10 -03:00
Torsten Grote
ef1d5d3233 Show lock icon when Briar is locked 2018-08-10 07:44:10 -03:00
Torsten Grote
feab825865 Don't show UnlockActivity anymore, might get removed completetly later 2018-08-10 07:44:10 -03:00
Torsten Grote
5d2c96f916 Remove LOCK button from foreground notification
When the user removes the screen lock, the app does not get really
locked. There is no way about getting notified about this. Before users
lock the app without it getting actually locked, we rather remove the
button that was collapsed and not easy to find anyway.
2018-08-10 07:44:10 -03:00
Torsten Grote
02ff37b187 Screen Lock: Second round of addressing review comments 2018-08-10 07:44:10 -03:00
Torsten Grote
6863727646 Upgrade robolectric to get Keyguard support for tests 2018-08-10 07:44:10 -03:00
Torsten Grote
087d6e9931 Screen Lock: Address first round of review comments 2018-08-10 07:44:10 -03:00
Torsten Grote
d79f1b667a Move app locking logic into dedicatd LockManager 2018-08-10 07:44:10 -03:00
Torsten Grote
633f5a8bd7 Adapt foreground notification when locked and show LOCK button 2018-08-10 07:44:10 -03:00
Torsten Grote
90cb9a2fae Disable screen lock setting instead of hiding it when not available 2018-08-10 07:44:10 -03:00
Torsten Grote
fc86319e13 MVP of PIN lock feature
This only shows the settings if a screen lock is available.
If the setting is activated, it shows a drawer item for locking.
Once locked, the screen lock secret needs to be entered to enter the
app again.

First part of #1247
2018-08-10 07:44:10 -03:00
Torsten Grote
af1ed292ae Merge branch '832-android-tor-plugin' into 'master'
Factor out Android-specific code from TorPlugin

Closes #832

See merge request briar/briar!876
2018-08-09 19:36:00 +00:00
Torsten Grote
5393127400 Merge branch 'show-blocked-country-names' into 'master'
Show names of countries where Tor is blocked

See merge request briar/briar!886
2018-08-09 13:21:22 +00:00
akwizgran
0e6c374d0e Show names of countries where Tor is blocked. 2018-08-09 13:55:06 +01:00
akwizgran
52efbcac8a Merge branch '1360-rename-main-flavor' into 'master'
Rename main flavor due to internal conflicts

Closes #1360

See merge request briar/briar!885
2018-08-09 08:58:24 +00:00
Torsten Grote
acf6a45004 Merge branch 'replace-assert-statements' into 'master'
Replace assert statements with AssertionErrors

See merge request briar/briar!877
2018-08-08 19:56:38 +00:00
Torsten Grote
7ffcace228 Rename Main Flavor due to internal conflicts 2018-08-08 16:52:28 -03:00
akwizgran
e157fdfc7b Merge branch '1251-dark-theme-old-message-bubbles' into 'master'
Dark Theme Changes

See merge request briar/briar!884
2018-08-08 15:18:50 +00:00
akwizgran
f8a8c0d8b8 Revert to old message bubbles pending design changes. 2018-08-08 10:35:05 +01:00
Torsten Grote
f53aeef0d6 Merge branch 'logger-names' into 'master'
Use full class names for loggers

See merge request briar/briar!881
2018-08-07 14:27:57 +00:00
akwizgran
f812acb00b Use general-purpose resource provider. 2018-08-07 15:19:46 +01:00
akwizgran
004467e84e Factor out remaining Android code from Tor plugin. 2018-08-07 15:19:43 +01:00
akwizgran
34c0a83e36 Use full class names for loggers. 2018-08-07 15:17:19 +01:00
Torsten Grote
fd0dad8936 Restore old button size and ensure timestamps are not selectable 2018-08-06 14:26:02 -03:00
Torsten Grote
32420a0781 Give names to colors and clean them up 2018-08-06 13:16:53 -03:00
Torsten Grote
b6c85c8bf6 More Dark Theme Changes after designer feedback 2018-08-06 13:16:53 -03:00
Torsten Grote
4163731ec3 New private message bubbles
This gets rid of all those pesky 9-Patch drawables
2018-08-06 13:16:53 -03:00
akwizgran
8e732d880f Merge branch '47-sign-in-reminder' into 'master'
Do not show sign-in reminder once PasswordActivity was opened

Closes #47

See merge request briar/briar!879
2018-08-06 09:38:05 +00:00
Torsten Grote
0b2594a693 Move SignIn reminder code into AndroidNotificationManager and don't show reminder once PasswordActivity was opened 2018-08-03 15:08:57 -03:00
akwizgran
5a145c9eb2 Replace assert statements with AssertionErrors. 2018-08-03 11:14:15 +01:00
147 changed files with 1510 additions and 989 deletions

View File

@@ -11,8 +11,8 @@ test:
- .gradle/caches - .gradle/caches
script: script:
- ./gradlew --no-daemon animalSnifferMain animalSnifferTest - ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest
- ./gradlew --no-daemon test - ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom test
after_script: after_script:
# these file change every time but should not be cached # these file change every time but should not be cached

View File

@@ -1,5 +1,6 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: 'witness' apply plugin: 'witness'
apply from: 'witness.gradle'
android { android {
compileSdkVersion 27 compileSdkVersion 27
@@ -27,7 +28,6 @@ configurations {
dependencies { dependencies {
implementation project(path: ':bramble-core', configuration: 'default') implementation project(path: ':bramble-core', configuration: 'default')
implementation 'org.briarproject:jtorctl:0.3'
tor 'org.briarproject:tor-android:0.2.9.16@zip' tor 'org.briarproject:tor-android:0.2.9.16@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2' annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
@@ -49,105 +49,14 @@ dependencies {
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0' androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
} }
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.support.test:monitor:1.0.2:monitor-1.0.2.aar:38ef4fa98a32dc55550ff49bb36a583e178b3a9b830fcb8dcc27bfc4254bc2bc',
'com.android.support.test:runner:1.0.2:runner-1.0.2.aar:f04b9ae342975ba1cb3e4a06e13426e3e6b8a73faa45acba604493d83c9a4f00',
'com.android.support:support-annotations:27.1.1:support-annotations-27.1.1.jar:3365960206c3d2b09e845f555e7f88f8effc8d2f00b369e66c4be384029299cf',
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
'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.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'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',
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'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',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
'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:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
'org.briarproject:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae',
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'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.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.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
'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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
]
}
project.afterEvaluate { project.afterEvaluate {
copy { copy {
from configurations.tor.collect { zipTree(it) } from configurations.tor.collect { zipTree(it) }
into 'src/main/res/raw' into 'src/main/res/raw'
} }
} }
tasks.withType(Test) {
// Use entropy-gathering device specified on command line, if any
systemProperty 'java.security.egd', System.getProperty('java.security.egd')
}

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.test.BrambleAndroidIntegrationTestComponent; import org.briarproject.bramble.test.BrambleAndroidIntegrationTestComponent;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.DaggerBrambleAndroidIntegrationTestComponent; import org.briarproject.bramble.test.DaggerBrambleAndroidIntegrationTestComponent;
@@ -40,43 +41,28 @@ public class BridgeTest extends BrambleTestCase {
private final static long TIMEOUT = SECONDS.toMillis(23); private final static long TIMEOUT = SECONDS.toMillis(23);
private final static Logger LOG = private final static Logger LOG =
Logger.getLogger(BridgeTest.class.getSimpleName()); Logger.getLogger(BridgeTest.class.getName());
@Inject @Inject
NetworkManager networkManager; NetworkManager networkManager;
@Inject @Inject
ResourceProvider resourceProvider;
@Inject
CircumventionProvider circumventionProvider;
@Inject
EventBus eventBus; EventBus eventBus;
@Inject @Inject
BackoffFactory backoffFactory; BackoffFactory backoffFactory;
@Inject @Inject
Clock clock; Clock clock;
private final Context appContext = getTargetContext(); private final Context appContext =
private final CircumventionProvider circumventionProvider; getTargetContext().getApplicationContext();
private final List<String> bridges;
private TorPluginFactory factory;
private volatile int currentBridge = 0;
public BridgeTest() { private List<String> bridges;
super(); private AndroidTorPluginFactory factory;
circumventionProvider = new CircumventionProvider() {
@Override
public boolean isTorProbablyBlocked(String countryCode) {
return true;
}
@Override private volatile String currentBridge = null;
public boolean doBridgesWork(String countryCode) {
return true;
}
@Override
public List<String> getBridges() {
return singletonList(bridges.get(currentBridge));
}
};
bridges = new CircumventionProviderImpl(appContext).getBridges();
}
@Before @Before
public void setUp() { public void setUp() {
@@ -89,28 +75,43 @@ public class BridgeTest extends BrambleTestCase {
LocationUtils locationUtils = () -> "US"; LocationUtils locationUtils = () -> "US";
SocketFactory torSocketFactory = SocketFactory.getDefault(); SocketFactory torSocketFactory = SocketFactory.getDefault();
factory = new TorPluginFactory(ioExecutor, scheduler, appContext, bridges = circumventionProvider.getBridges();
CircumventionProvider bridgeProvider = new CircumventionProvider() {
@Override
public boolean isTorProbablyBlocked(String countryCode) {
return true;
}
@Override
public boolean doBridgesWork(String countryCode) {
return true;
}
@Override
public List<String> getBridges() {
return singletonList(currentBridge);
}
};
factory = new AndroidTorPluginFactory(ioExecutor, scheduler, appContext,
networkManager, locationUtils, eventBus, torSocketFactory, networkManager, locationUtils, eventBus, torSocketFactory,
backoffFactory, circumventionProvider, clock); backoffFactory, resourceProvider, bridgeProvider, clock);
} }
@Test @Test
public void testBridges() throws Exception { public void testBridges() throws Exception {
assertTrue(bridges.size() > 0); assertTrue(bridges.size() > 0);
for (int i = 0; i < bridges.size(); i++) { for (String bridge : bridges) testBridge(bridge);
testBridge(i);
}
} }
private void testBridge(int bridge) throws Exception { private void testBridge(String bridge) throws Exception {
DuplexPlugin duplexPlugin = DuplexPlugin duplexPlugin =
factory.createPlugin(new TorPluginCallBack()); factory.createPlugin(new TorPluginCallBack());
assertNotNull(duplexPlugin); assertNotNull(duplexPlugin);
TorPlugin plugin = (TorPlugin) duplexPlugin; AndroidTorPlugin plugin = (AndroidTorPlugin) duplexPlugin;
currentBridge = bridge; currentBridge = bridge;
LOG.warning("Testing " + bridges.get(currentBridge)); LOG.warning("Testing " + bridge);
try { try {
plugin.start(); plugin.start();
long start = clock.currentTimeMillis(); long start = clock.currentTimeMillis();

View File

@@ -1,20 +1,20 @@
package org.briarproject.bramble.test; package org.briarproject.bramble.test;
import android.app.Application; import android.app.Application;
import android.support.test.InstrumentationRegistry;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import static android.support.test.InstrumentationRegistry.getTargetContext;
@Module @Module
class ApplicationModule { class ApplicationModule {
@Provides @Provides
@Singleton @Singleton
Application provideApplication() { Application provideApplication() {
return (Application) InstrumentationRegistry.getTargetContext() return (Application) getTargetContext().getApplicationContext();
.getApplicationContext();
} }
} }

View File

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

View File

@@ -91,7 +91,7 @@ class AndroidNetworkManager implements NetworkManager, Service {
public NetworkStatus getNetworkStatus() { public NetworkStatus getNetworkStatus() {
ConnectivityManager cm = (ConnectivityManager) ConnectivityManager cm = (ConnectivityManager)
appContext.getSystemService(CONNECTIVITY_SERVICE); appContext.getSystemService(CONNECTIVITY_SERVICE);
assert cm != null; if (cm == null) throw new AssertionError();
NetworkInfo net = cm.getActiveNetworkInfo(); NetworkInfo net = cm.getActiveNetworkInfo();
boolean connected = net != null && net.isConnected(); boolean connected = net != null && net.isConnected();
boolean wifi = connected && net.getType() == TYPE_WIFI; boolean wifi = connected && net.getType() == TYPE_WIFI;

View File

@@ -68,7 +68,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1); new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1);
ConnectivityManager connectivityManager = (ConnectivityManager) ConnectivityManager connectivityManager = (ConnectivityManager)
appContext.getSystemService(CONNECTIVITY_SERVICE); appContext.getSystemService(CONNECTIVITY_SERVICE);
assert connectivityManager != null; if (connectivityManager == null) throw new AssertionError();
this.connectivityManager = connectivityManager; this.connectivityManager = connectivityManager;
wifiManager = (WifiManager) appContext.getApplicationContext() wifiManager = (WifiManager) appContext.getApplicationContext()
.getSystemService(WIFI_SERVICE); .getSystemService(WIFI_SERVICE);

View File

@@ -0,0 +1,88 @@
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
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.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
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 java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
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;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidTorPlugin extends TorPlugin {
// This tag may prevent Huawei's power manager from killing us
private static final String WAKE_LOCK_TAG = "LocationManagerService";
private final Context appContext;
private final RenewableWakeLock wakeLock;
AndroidTorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
Context appContext, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, backoff,
callback, architecture, maxLatency, maxIdleTime,
appContext.getDir("tor", MODE_PRIVATE));
this.appContext = appContext;
PowerManager pm = (PowerManager)
appContext.getSystemService(POWER_SERVICE);
assert pm != null;
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
WAKE_LOCK_TAG, 1, MINUTES);
}
@Override
protected int getProcessId() {
return android.os.Process.myPid();
}
@Override
protected long getLastUpdateTime() {
try {
PackageManager pm = appContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0);
return pi.lastUpdateTime;
} catch (NameNotFoundException e) {
throw new AssertionError(e);
}
}
@Override
protected void enableNetwork(boolean enable) throws IOException {
if (!running) return;
if (enable) wakeLock.acquire();
super.enableNetwork(enable);
if (!enable) wakeLock.release();
}
@Override
public void stop() {
super.stop();
wakeLock.release();
}
}

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.AndroidUtils; import org.briarproject.bramble.util.AndroidUtils;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -26,10 +27,10 @@ import javax.net.SocketFactory;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class TorPluginFactory implements DuplexPluginFactory { public class AndroidTorPluginFactory implements DuplexPluginFactory {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(TorPluginFactory.class.getName()); Logger.getLogger(AndroidTorPluginFactory.class.getName());
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds 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 MAX_IDLE_TIME = 30 * 1000; // 30 seconds
@@ -45,14 +46,15 @@ public class TorPluginFactory implements DuplexPluginFactory {
private final EventBus eventBus; private final EventBus eventBus;
private final SocketFactory torSocketFactory; private final SocketFactory torSocketFactory;
private final BackoffFactory backoffFactory; private final BackoffFactory backoffFactory;
private final ResourceProvider resourceProvider;
private final CircumventionProvider circumventionProvider; private final CircumventionProvider circumventionProvider;
private final Clock clock; private final Clock clock;
public TorPluginFactory(Executor ioExecutor, public AndroidTorPluginFactory(Executor ioExecutor,
ScheduledExecutorService scheduler, Context appContext, ScheduledExecutorService scheduler, Context appContext,
NetworkManager networkManager, LocationUtils locationUtils, NetworkManager networkManager, LocationUtils locationUtils,
EventBus eventBus, SocketFactory torSocketFactory, EventBus eventBus, SocketFactory torSocketFactory,
BackoffFactory backoffFactory, BackoffFactory backoffFactory, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, Clock clock) { CircumventionProvider circumventionProvider, Clock clock) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.scheduler = scheduler; this.scheduler = scheduler;
@@ -62,6 +64,7 @@ public class TorPluginFactory implements DuplexPluginFactory {
this.eventBus = eventBus; this.eventBus = eventBus;
this.torSocketFactory = torSocketFactory; this.torSocketFactory = torSocketFactory;
this.backoffFactory = backoffFactory; this.backoffFactory = backoffFactory;
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider; this.circumventionProvider = circumventionProvider;
this.clock = clock; this.clock = clock;
} }
@@ -99,10 +102,10 @@ public class TorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorPlugin plugin = new TorPlugin(ioExecutor, scheduler, appContext, AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
networkManager, locationUtils, torSocketFactory, clock, appContext, networkManager, locationUtils, torSocketFactory,
circumventionProvider, backoff, callback, architecture, clock, resourceProvider, circumventionProvider, backoff,
MAX_LATENCY, MAX_IDLE_TIME); callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -0,0 +1,30 @@
package org.briarproject.bramble.system;
import android.app.Application;
import android.content.Context;
import android.content.res.Resources;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.ResourceProvider;
import java.io.InputStream;
import javax.inject.Inject;
@NotNullByDefault
class AndroidResourceProvider implements ResourceProvider {
private final Context appContext;
@Inject
AndroidResourceProvider(Application app) {
this.appContext = app.getApplicationContext();
}
@Override
public InputStream getResourceInputStream(String name) {
Resources res = appContext.getResources();
int resId = res.getIdentifier(name, "raw", appContext.getPackageName());
return res.openRawResource(resId);
}
}

View File

@@ -1,9 +1,8 @@
package org.briarproject.bramble.system; package org.briarproject.bramble.system;
import android.app.Application;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.SecureRandomProvider; import org.briarproject.bramble.api.system.SecureRandomProvider;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -16,18 +15,26 @@ public class AndroidSystemModule {
@Provides @Provides
@Singleton @Singleton
SecureRandomProvider provideSecureRandomProvider(Application app) { SecureRandomProvider provideSecureRandomProvider(
return new AndroidSecureRandomProvider(app); AndroidSecureRandomProvider provider) {
return provider;
} }
@Provides @Provides
LocationUtils provideLocationUtils(Application app) { LocationUtils provideLocationUtils(AndroidLocationUtils locationUtils) {
return new AndroidLocationUtils(app); return locationUtils;
} }
@Provides @Provides
@Singleton @Singleton
AndroidExecutor provideAndroidExecutor(Application app) { AndroidExecutor provideAndroidExecutor(
return new AndroidExecutorImpl(app); AndroidExecutorImpl androidExecutor) {
return androidExecutor;
}
@Provides
@Singleton
ResourceProvider provideResourceProvider(AndroidResourceProvider provider) {
return provider;
} }
} }

View File

@@ -0,0 +1,94 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.support.test:monitor:1.0.2:monitor-1.0.2.aar:38ef4fa98a32dc55550ff49bb36a583e178b3a9b830fcb8dcc27bfc4254bc2bc',
'com.android.support.test:runner:1.0.2:runner-1.0.2.aar:f04b9ae342975ba1cb3e4a06e13426e3e6b8a73faa45acba604493d83c9a4f00',
'com.android.support:support-annotations:27.1.1:support-annotations-27.1.1.jar:3365960206c3d2b09e845f555e7f88f8effc8d2f00b369e66c4be384029299cf',
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
'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.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'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',
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'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',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
'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:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae',
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'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.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.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
'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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
]
}

View File

@@ -4,6 +4,7 @@ targetCompatibility = 1.8
apply plugin: 'ru.vyarus.animalsniffer' apply plugin: 'ru.vyarus.animalsniffer'
apply plugin: 'witness' apply plugin: 'witness'
apply from: 'witness.gradle'
dependencies { dependencies {
implementation "com.google.dagger:dagger:2.0.2" implementation "com.google.dagger:dagger:2.0.2"
@@ -19,31 +20,6 @@ dependencies {
signature 'org.codehaus.mojo.signature:java16:1.1@signature' signature 'org.codehaus.mojo.signature:java16:1.1@signature'
} }
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'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.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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
]
}
// needed to make test output available to bramble-core and briar-core // needed to make test output available to bramble-core and briar-core
configurations { configurations {
testOutput.extendsFrom(testCompile) testOutput.extendsFrom(testCompile)
@@ -55,3 +31,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
artifacts { artifacts {
testOutput jarTest testOutput jarTest
} }
tasks.withType(Test) {
// Use entropy-gathering device specified on command line, if any
systemProperty 'java.security.egd', System.getProperty('java.security.egd')
}

View File

@@ -7,16 +7,6 @@ public interface KeyAgreementConstants {
*/ */
byte PROTOCOL_VERSION = 4; byte PROTOCOL_VERSION = 4;
/**
* The length of the record header in bytes.
*/
int RECORD_HEADER_LENGTH = 4;
/**
* The offset of the payload length in the record header, in bytes.
*/
int RECORD_HEADER_PAYLOAD_LENGTH_OFFSET = 2;
/** /**
* The length of the BQP key commitment in bytes. * The length of the BQP key commitment in bytes.
*/ */

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.system;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.InputStream;
@NotNullByDefault
public interface ResourceProvider {
InputStream getResourceInputStream(String name);
}

View File

@@ -0,0 +1,24 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'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.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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
]
}

View File

@@ -6,6 +6,7 @@ apply plugin: 'ru.vyarus.animalsniffer'
apply plugin: 'net.ltgt.apt' apply plugin: 'net.ltgt.apt'
apply plugin: 'idea' apply plugin: 'idea'
apply plugin: 'witness' apply plugin: 'witness'
apply from: 'witness.gradle'
dependencies { dependencies {
implementation project(path: ':bramble-api', configuration: 'default') implementation project(path: ':bramble-api', configuration: 'default')
@@ -14,6 +15,7 @@ dependencies {
implementation 'org.bitlet:weupnp:0.1.4' implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0' implementation 'net.i2p.crypto:eddsa:0.2.0'
implementation 'org.whispersystems:curve25519-java:0.4.1' implementation 'org.whispersystems:curve25519-java:0.4.1'
implementation 'org.briarproject:jtorctl:0.3'
apt 'com.google.dagger:dagger-compiler:2.0.2' apt 'com.google.dagger:dagger-compiler:2.0.2'
@@ -31,39 +33,6 @@ dependencies {
signature 'org.codehaus.mojo.signature:java16:1.1@signature' signature 'org.codehaus.mojo.signature:java16:1.1@signature'
} }
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'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.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.whispersystems:curve25519-java:0.4.1:curve25519-java-0.4.1.jar:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e',
]
}
// needed to make test output available to bramble-j2se // needed to make test output available to bramble-j2se
configurations { configurations {
testOutput.extendsFrom(testCompile) testOutput.extendsFrom(testCompile)
@@ -75,3 +44,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
artifacts { artifacts {
testOutput jarTest testOutput jarTest
} }
tasks.withType(Test) {
// Use entropy-gathering device specified on command line, if any
systemProperty 'java.security.egd', System.getProperty('java.security.egd')
}

View File

@@ -0,0 +1,17 @@
package org.briarproject.bramble.plugin.tor;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class CircumventionModule {
@Provides
@Singleton
CircumventionProvider provideCircumventionProvider(
CircumventionProviderImpl provider) {
return provider;
}
}

View File

@@ -1,13 +1,10 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.content.res.Resources;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.system.ResourceProvider;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Scanner; import java.util.Scanner;
@@ -16,26 +13,27 @@ import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
// TODO: Create a module for this so it doesn't need to be public import static java.util.Arrays.asList;
public class CircumventionProviderImpl implements CircumventionProvider { class CircumventionProviderImpl implements CircumventionProvider {
private final static String BRIDGE_FILE_NAME = "bridges"; private final static String BRIDGE_FILE_NAME = "bridges";
private final Context ctx; private static final Set<String> BLOCKED_IN_COUNTRIES =
new HashSet<>(asList(BLOCKED));
private static final Set<String> BRIDGES_WORK_IN_COUNTRIES =
new HashSet<>(asList(BRIDGES));
private final ResourceProvider resourceProvider;
@Nullable @Nullable
private volatile List<String> bridges = null; private volatile List<String> bridges = null;
@Inject @Inject
public CircumventionProviderImpl(Context ctx) { CircumventionProviderImpl(ResourceProvider resourceProvider) {
this.ctx = ctx; this.resourceProvider = resourceProvider;
} }
private static final Set<String> BLOCKED_IN_COUNTRIES =
new HashSet<>(Arrays.asList(BLOCKED));
private static final Set<String> BRIDGES_WORK_IN_COUNTRIES =
new HashSet<>(Arrays.asList(BRIDGES));
@Override @Override
public boolean isTorProbablyBlocked(String countryCode) { public boolean isTorProbablyBlocked(String countryCode) {
return BLOCKED_IN_COUNTRIES.contains(countryCode); return BLOCKED_IN_COUNTRIES.contains(countryCode);
@@ -49,15 +47,14 @@ public class CircumventionProviderImpl implements CircumventionProvider {
@Override @Override
@IoExecutor @IoExecutor
public List<String> getBridges() { public List<String> getBridges() {
if (this.bridges != null) return this.bridges; List<String> bridges = this.bridges;
if (bridges != null) return new ArrayList<>(bridges);
Resources res = ctx.getResources(); InputStream is =
int resId = res.getIdentifier(BRIDGE_FILE_NAME, "raw", resourceProvider.getResourceInputStream(BRIDGE_FILE_NAME);
ctx.getPackageName());
InputStream is = ctx.getResources().openRawResource(resId);
Scanner scanner = new Scanner(is); Scanner scanner = new Scanner(is);
List<String> bridges = new ArrayList<>(); bridges = new ArrayList<>();
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();
if (!line.startsWith("#")) bridges.add(line); if (!line.startsWith("#")) bridges.add(line);

View File

@@ -1,12 +1,5 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.os.PowerManager;
import net.freehaven.tor.control.EventHandler; import net.freehaven.tor.control.EventHandler;
import net.freehaven.tor.control.TorControlConnection; import net.freehaven.tor.control.TorControlConnection;
@@ -33,8 +26,8 @@ import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent; import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.RenewableWakeLock;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable; import java.io.Closeable;
@@ -57,7 +50,6 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -66,10 +58,6 @@ import java.util.zip.ZipInputStream;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.net.SocketFactory; 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 java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS; import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
@@ -88,7 +76,10 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
class TorPlugin implements DuplexPlugin, EventHandler, EventListener { abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final Logger LOG =
Logger.getLogger(TorPlugin.class.getName());
private static final String[] EVENTS = { private static final String[] EVENTS = {
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR" "CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
@@ -97,13 +88,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final int COOKIE_TIMEOUT_MS = 3000; private static final int COOKIE_TIMEOUT_MS = 3000;
private static final int COOKIE_POLLING_INTERVAL_MS = 200; private static final int COOKIE_POLLING_INTERVAL_MS = 200;
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}"); private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
// This tag may prevent Huawei's power manager from killing us
private static final String WAKE_LOCK_TAG = "LocationManagerService";
private static final Logger LOG =
Logger.getLogger(TorPlugin.class.getName());
private final Executor ioExecutor, connectionStatusExecutor; private final Executor ioExecutor, connectionStatusExecutor;
private final Context appContext;
private final NetworkManager networkManager; private final NetworkManager networkManager;
private final LocationUtils locationUtils; private final LocationUtils locationUtils;
private final SocketFactory torSocketFactory; private final SocketFactory torSocketFactory;
@@ -112,53 +98,54 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final DuplexPluginCallback callback; private final DuplexPluginCallback callback;
private final String architecture; private final String architecture;
private final CircumventionProvider circumventionProvider; private final CircumventionProvider circumventionProvider;
private final ResourceProvider resourceProvider;
private final int maxLatency, maxIdleTime, socketTimeout; private final int maxLatency, maxIdleTime, socketTimeout;
private final ConnectionStatus connectionStatus;
private final File torDirectory, torFile, geoIpFile, configFile; private final File torDirectory, torFile, geoIpFile, configFile;
private final File doneFile, cookieFile; private final File doneFile, cookieFile;
private final RenewableWakeLock wakeLock; private final ConnectionStatus connectionStatus;
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
private volatile boolean running = false;
private volatile ServerSocket socket = null; private volatile ServerSocket socket = null;
private volatile Socket controlSocket = null; private volatile Socket controlSocket = null;
private volatile TorControlConnection controlConnection = null; private volatile TorControlConnection controlConnection = null;
TorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler, protected volatile boolean running = false;
Context appContext, NetworkManager networkManager,
protected abstract int getProcessId();
protected abstract long getLastUpdateTime();
TorPlugin(Executor ioExecutor, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory, LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, CircumventionProvider circumventionProvider, Clock clock, ResourceProvider resourceProvider,
Backoff backoff, DuplexPluginCallback callback, CircumventionProvider circumventionProvider, Backoff backoff,
String architecture, int maxLatency, int maxIdleTime) { DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.appContext = appContext;
this.networkManager = networkManager; this.networkManager = networkManager;
this.locationUtils = locationUtils; this.locationUtils = locationUtils;
this.torSocketFactory = torSocketFactory; this.torSocketFactory = torSocketFactory;
this.clock = clock; this.clock = clock;
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider;
this.backoff = backoff; this.backoff = backoff;
this.callback = callback; this.callback = callback;
this.architecture = architecture; this.architecture = architecture;
this.circumventionProvider = circumventionProvider;
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime; this.maxIdleTime = maxIdleTime;
if (maxIdleTime > Integer.MAX_VALUE / 2) if (maxIdleTime > Integer.MAX_VALUE / 2)
socketTimeout = Integer.MAX_VALUE; socketTimeout = Integer.MAX_VALUE;
else socketTimeout = maxIdleTime * 2; else socketTimeout = maxIdleTime * 2;
connectionStatus = new ConnectionStatus(); this.torDirectory = torDirectory;
torDirectory = appContext.getDir("tor", MODE_PRIVATE);
torFile = new File(torDirectory, "tor"); torFile = new File(torDirectory, "tor");
geoIpFile = new File(torDirectory, "geoip"); geoIpFile = new File(torDirectory, "geoip");
configFile = new File(torDirectory, "torrc"); configFile = new File(torDirectory, "torrc");
doneFile = new File(torDirectory, "done"); doneFile = new File(torDirectory, "done");
cookieFile = new File(torDirectory, ".tor/control_auth_cookie"); cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
connectionStatus = new ConnectionStatus();
// Don't execute more than one connection status check at a time // Don't execute more than one connection status check at a time
connectionStatusExecutor = connectionStatusExecutor =
new PoliteExecutor("TorPlugin", ioExecutor, 1); new PoliteExecutor("TorPlugin", ioExecutor, 1);
PowerManager pm = (PowerManager)
appContext.getSystemService(POWER_SERVICE);
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
WAKE_LOCK_TAG, 1, MINUTES);
} }
@Override @Override
@@ -187,7 +174,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
LOG.info("Starting Tor"); LOG.info("Starting Tor");
String torPath = torFile.getAbsolutePath(); String torPath = torFile.getAbsolutePath();
String configPath = configFile.getAbsolutePath(); String configPath = configFile.getAbsolutePath();
String pid = String.valueOf(android.os.Process.myPid()); String pid = String.valueOf(getProcessId());
Process torProcess; Process torProcess;
ProcessBuilder pb = ProcessBuilder pb =
new ProcessBuilder(torPath, "-f", configPath, OWNER, pid); new ProcessBuilder(torPath, "-f", configPath, OWNER, pid);
@@ -266,13 +253,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
private boolean assetsAreUpToDate() { private boolean assetsAreUpToDate() {
try { return doneFile.lastModified() > getLastUpdateTime();
PackageManager pm = appContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0);
return doneFile.lastModified() > pi.lastUpdateTime;
} catch (NameNotFoundException e) {
throw new RuntimeException(e);
}
} }
private void installAssets() throws PluginException { private void installAssets() throws PluginException {
@@ -305,29 +286,22 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private InputStream getTorInputStream() throws IOException { private InputStream getTorInputStream() throws IOException {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Installing Tor binary for " + architecture); LOG.info("Installing Tor binary for " + architecture);
int resId = getResourceId("tor_" + architecture); InputStream in =
InputStream in = appContext.getResources().openRawResource(resId); resourceProvider.getResourceInputStream("tor_" + architecture);
ZipInputStream zin = new ZipInputStream(in); ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException(); if (zin.getNextEntry() == null) throw new IOException();
return zin; return zin;
} }
private InputStream getGeoIpInputStream() throws IOException { private InputStream getGeoIpInputStream() throws IOException {
int resId = getResourceId("geoip"); InputStream in = resourceProvider.getResourceInputStream("geoip");
InputStream in = appContext.getResources().openRawResource(resId);
ZipInputStream zin = new ZipInputStream(in); ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException(); if (zin.getNextEntry() == null) throw new IOException();
return zin; return zin;
} }
private InputStream getConfigInputStream() { private InputStream getConfigInputStream() {
int resId = getResourceId("torrc"); return resourceProvider.getResourceInputStream("torrc");
return appContext.getResources().openRawResource(resId);
}
private int getResourceId(String filename) {
Resources res = appContext.getResources();
return res.getIdentifier(filename, "raw", appContext.getPackageName());
} }
private void tryToClose(@Nullable Closeable c) { private void tryToClose(@Nullable Closeable c) {
@@ -473,15 +447,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
} }
private void enableNetwork(boolean enable) throws IOException { protected void enableNetwork(boolean enable) throws IOException {
if (!running) return; if (!running) return;
if (enable) wakeLock.acquire();
connectionStatus.enableNetwork(enable); connectionStatus.enableNetwork(enable);
controlConnection.setConf("DisableNetwork", enable ? "0" : "1"); controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
if (!enable) { if (!enable) callback.transportDisabled();
callback.transportDisabled();
wakeLock.release();
}
} }
private void enableBridges(boolean enable) throws IOException { private void enableBridges(boolean enable) throws IOException {
@@ -509,7 +479,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
} }
} }
wakeLock.release();
} }
@Override @Override

View File

@@ -46,7 +46,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
} }
private void readRecord() throws IOException { private void readRecord() throws IOException {
assert nextRecord == null; if (nextRecord != null) throw new AssertionError();
while (true) { while (true) {
nextRecord = reader.readRecord(); nextRecord = reader.readRecord();
// Check the protocol version // Check the protocol version
@@ -62,7 +62,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
} }
private byte getNextRecordType() { private byte getNextRecordType() {
assert nextRecord != null; if (nextRecord == null) throw new AssertionError();
return nextRecord.getRecordType(); return nextRecord.getRecordType();
} }
@@ -100,7 +100,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
} }
private List<MessageId> readMessageIds() throws IOException { private List<MessageId> readMessageIds() throws IOException {
assert nextRecord != null; if (nextRecord == null) throw new AssertionError();
byte[] payload = nextRecord.getPayload(); byte[] payload = nextRecord.getPayload();
if (payload.length == 0) throw new FormatException(); if (payload.length == 0) throw new FormatException();
if (payload.length % UniqueId.LENGTH != 0) throw new FormatException(); if (payload.length % UniqueId.LENGTH != 0) throw new FormatException();
@@ -122,7 +122,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
@Override @Override
public Message readMessage() throws IOException { public Message readMessage() throws IOException {
if (!hasMessage()) throw new FormatException(); if (!hasMessage()) throw new FormatException();
assert nextRecord != null; if (nextRecord == null) throw new AssertionError();
byte[] payload = nextRecord.getPayload(); byte[] payload = nextRecord.getPayload();
if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException(); if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException();
// Validate timestamp // Validate timestamp

View File

@@ -0,0 +1,33 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'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.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.whispersystems:curve25519-java:0.4.1:curve25519-java-0.4.1.jar:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e',
]
}

View File

@@ -5,6 +5,7 @@ targetCompatibility = 1.8
apply plugin: 'net.ltgt.apt' apply plugin: 'net.ltgt.apt'
apply plugin: 'idea' apply plugin: 'idea'
apply plugin: 'witness' apply plugin: 'witness'
apply from: 'witness.gradle'
dependencies { dependencies {
implementation project(path: ':bramble-core', configuration: 'default') implementation project(path: ':bramble-core', configuration: 'default')
@@ -24,31 +25,8 @@ dependencies {
testImplementation "org.hamcrest:hamcrest-core:1.3" testImplementation "org.hamcrest:hamcrest-core:1.3"
} }
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.java.dev.jna:jna-platform:4.4.0:jna-platform-4.4.0.jar:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
'net.java.dev.jna:jna:4.4.0:jna-4.4.0.jar:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'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.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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
]
}
tasks.withType(Test) { tasks.withType(Test) {
// Use entropy-gathering device specified on command line, if any
systemProperty 'java.security.egd', System.getProperty('java.security.egd')
systemProperty 'java.library.path', 'libs' systemProperty 'java.library.path', 'libs'
} }

View File

@@ -0,0 +1,24 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.java.dev.jna:jna-platform:4.4.0:jna-platform-4.4.0.jar:e9dda9e884fc107eb6367710540789a12dfa8ad28be9326b22ca6e352e325499',
'net.java.dev.jna:jna:4.4.0:jna-4.4.0.jar:c4dadeeecaa90c8847902082aee5eb107fcf59c5d0e63a17fcaf273c0e2d2bd1',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'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.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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
]
}

View File

@@ -1,5 +1,6 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'witness' apply plugin: 'witness'
apply from: 'witness.gradle'
dependencies { dependencies {
implementation project(path: ':briar-core', configuration: 'default') implementation project(path: ':briar-core', configuration: 'default')
@@ -40,9 +41,9 @@ dependencies {
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput') testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation 'org.robolectric:robolectric:3.5.1' testImplementation 'org.robolectric:robolectric:3.8'
testImplementation 'org.robolectric:shadows-support-v4:3.0' testImplementation 'org.robolectric:shadows-support-v4:3.3.2'
testImplementation 'org.mockito:mockito-core:2.8.9' testImplementation 'org.mockito:mockito-core:2.13.0'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2" testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2" testImplementation "org.jmock:jmock-junit4:2.8.2"
@@ -61,186 +62,6 @@ dependencies {
androidTestImplementation 'junit:junit:4.12' androidTestImplementation 'junit:junit:4.12'
} }
dependencyVerification {
verify = [
'android.arch.core:common:1.1.0:common-1.1.0.jar:d34824b794bc92ff8f647a9bb13a7c73de920de5b47075b5d2c4f0770e9b8bfd',
'android.arch.core:runtime:1.1.0:runtime-1.1.0.aar:83400f7575bcfb8a2eeec64e05590f037bfaed1e56aa3a4214d20e55878445e3',
'android.arch.lifecycle:common:1.1.0:common-1.1.0.jar:614e31cfd33255dc4d5f5d8e62cfa6be2fbbc2a35643a79dc3ed008004c30807',
'android.arch.lifecycle:livedata-core:1.1.0:livedata-core-1.1.0.aar:14e57ff8ffb65a80c7e72d91f2076acccdaf2970f234c6261e03a6127eb5206b',
'android.arch.lifecycle:runtime:1.1.0:runtime-1.1.0.aar:094fd793924dd6a5136753e599ac8174a8147f4a401386b694ba7d818c223e2e',
'android.arch.lifecycle:viewmodel:1.1.0:viewmodel-1.1.0.aar:6407c93a5ea9850661dca42a0068d6f3deccefd7228ee69bae1c35d70cbc2557',
'backport-util-concurrent:backport-util-concurrent:3.1:backport-util-concurrent-3.1.jar:f5759b7fcdfc83a525a036deedcbd32e5b536b625ebc282426f16ca137eb5902',
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'ch.acra:acra:4.9.1:acra-4.9.1.aar:d2762968c448757a7d6acc9f141881d9632f664988e9723ece33b5f7c79f3bc9',
'classworlds:classworlds:1.1-alpha-2:classworlds-1.1-alpha-2.jar:2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3',
'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05',
'com.android.support.constraint:constraint-layout-solver:1.1.0:constraint-layout-solver-1.1.0.jar:fcb4c7d705754ca3d69b1b2c3caf445a425599fda8caabbcf855d98ea0663e4e',
'com.android.support.constraint:constraint-layout:1.1.0:constraint-layout-1.1.0.aar:d490188709b7bb2f11609beadd7e5eb7538892f308828ec3ff261a74e6ecf47e',
'com.android.support.test.espresso:espresso-contrib:3.0.2:espresso-contrib-3.0.2.aar:eacb4a10dde5597b8a6b8668804d4b63e3ae2d46a78192068532922fec0b4a66',
'com.android.support.test.espresso:espresso-core:3.0.2:espresso-core-3.0.2.aar:f40bf62e26e6f95a9c376c4e318415a77053b7dbb7ec12688eb6fab93dffdf73',
'com.android.support.test.espresso:espresso-idling-resource:3.0.2:espresso-idling-resource-3.0.2.aar:c6485150f9f4aea1ce9d138f3d60d82ebed3fe35b340a8b1dc975ff01f3b17b2',
'com.android.support.test.espresso:espresso-intents:3.0.2:espresso-intents-3.0.2.aar:556f99e8c8723a9ef313ed816fb9074d65903c6767521a66b099720d2cc21f10',
'com.android.support.test.uiautomator:uiautomator-v18:2.1.3:uiautomator-v18-2.1.3.aar:15e6b3c7104859630bf844e31805aa7cb2eb4b385e6119ab34132c8258eee2c4',
'com.android.support.test:monitor:1.0.2:monitor-1.0.2.aar:38ef4fa98a32dc55550ff49bb36a583e178b3a9b830fcb8dcc27bfc4254bc2bc',
'com.android.support.test:rules:1.0.2:rules-1.0.2.aar:7ddad387d1a16d4dbdbefacee070d34574e565b008117c1a163edac8ae02a6aa',
'com.android.support.test:runner:1.0.2:runner-1.0.2.aar:f04b9ae342975ba1cb3e4a06e13426e3e6b8a73faa45acba604493d83c9a4f00',
'com.android.support:animated-vector-drawable:27.1.1:animated-vector-drawable-27.1.1.aar:59670473f6e98fda792f7bef25dd7292b0a3106031c7a5e30eb020bf26f077bd',
'com.android.support:appcompat-v7:27.1.1:appcompat-v7-27.1.1.aar:0c7808fbbc5838d831e32e3c0a6f84e1f2c981deb8f11e010650f2b57923a335',
'com.android.support:cardview-v7:27.1.1:cardview-v7-27.1.1.aar:8ed955dd037d82a7b4bbcaedb4f896523c3e4c1bf3ca698ce807c350767a2886',
'com.android.support:design:27.1.1:design-27.1.1.aar:7225973f7ee03765008a9c2f17a40b154c6885169fef022276e811c926a2202c',
'com.android.support:preference-v14:27.1.1:preference-v14-27.1.1.aar:dc058932e6fd93bf57d23fcc2f22351c21e5125e513721e4b0b03374341ad400',
'com.android.support:preference-v7:27.1.1:preference-v7-27.1.1.aar:a1798a826b4097d00e49280f412b21af08f9bf1179c2e3838dc339d9f843416d',
'com.android.support:recyclerview-v7:27.1.1:recyclerview-v7-27.1.1.aar:d735e4727878e99ef3980c10d15dc3468462fd509d4fb60cb8bd20b0f735085c',
'com.android.support:support-annotations:27.1.1:support-annotations-27.1.1.jar:3365960206c3d2b09e845f555e7f88f8effc8d2f00b369e66c4be384029299cf',
'com.android.support:support-compat:27.1.1:support-compat-27.1.1.aar:880ce01ff5be42b233ff8ec0c61cefb7dc3dc9500fea9e24423214813ac27ea2',
'com.android.support:support-core-ui:27.1.1:support-core-ui-27.1.1.aar:a3ae20e6d5dffba69ac97b99846d2738003af8563843d5f3c9dc4c35b4804241',
'com.android.support:support-core-utils:27.1.1:support-core-utils-27.1.1.aar:61036832c54e8701aae954fc3bf96d1d80bf8d9dd531bff77d72def456ba087a',
'com.android.support:support-fragment:27.1.1:support-fragment-27.1.1.aar:ec72d6ac36a1a0e6523bbddba33d73ffad070b9b3dd246cc44d8727a41ddb5e6',
'com.android.support:support-media-compat:27.1.1:support-media-compat-27.1.1.aar:55e9837dda88b74a8c812c63a78c63fd83c6c039a8c22d318492663a493585eb',
'com.android.support:support-v4:27.1.1:support-v4-27.1.1.aar:4f41dfc3e89f2738e45c86264a85c0934d055ee8ebe2020e23c97f303b80a48b',
'com.android.support:support-vector-drawable:27.1.1:support-vector-drawable-27.1.1.aar:1c0f421114cf4627cf208776d6eb4f76340c78b7e96fe6e12b3e6eb950caf1b9',
'com.android.support:transition:27.1.1:transition-27.1.1.aar:c0765b2f3c78696567ec5b3f519d22da1e3df11ac994625adf4bb4dc571caacc',
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
'com.github.bumptech.glide:glide:3.8.0:glide-3.8.0.jar:750d9e7b940dc0ee48f8680623b55d46e14e8727acc922d7b156e57e7c549655',
'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.0:accessibility-test-framework-2.0.jar:cdf16ef8f5b8023d003ce3cc1b0d51bda737762e2dab2fedf43d1c4292353f7f',
'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.1:accessibility-test-framework-2.1.jar:7b0aa6ed7553597ce0610684a9f7eca8021eee218f2e2f427c04a7fbf5f920bd',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.google.guava:guava:20.0:guava-20.0.jar:36a666e3b71ae7f0f0dca23654b67e086e6c93d192f60ba5dfd5519db6c288c8',
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
'com.google.protobuf:protobuf-java:2.6.1:protobuf-java-2.6.1.jar:55aa554843983f431df5616112cf688d38aa17c132357afd1c109435bfdac4e6',
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
'com.google.zxing:core:3.3.0:core-3.3.0.jar:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
'com.jpardogo.materialtabstrip:library:1.1.0:library-1.1.0.aar:24d19232b319f8c73e25793432357919a7ed972186f57a3b2c9093ea74ad8311',
'com.squareup:javawriter:2.1.1:javawriter-2.1.1.jar:f699823d0081f69cbb676c1845ea222e0ada79bc88a53e5d22d8bd02d328f57e',
'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.thoughtworks.xstream:xstream:1.4.8:xstream-1.4.8.jar:a219a1abf948400b669d08be73a6f9209fb720d237e5ff74c223bffe5f9df93d',
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
'de.hdodenhof:circleimageview:2.2.0:circleimageview-2.2.0.aar:bc34761dcd5036229ac1ffed6b5b1bef722ad5b097a2c8bba1c5ed2cd4b5c82b',
'info.guardianproject.panic:panic:0.5:panic-0.5.jar:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2',
'info.guardianproject.trustedintents:trustedintents:0.2:trustedintents-0.2.jar:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'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',
'nekohtml:nekohtml:1.9.6.2:nekohtml-1.9.6.2.jar:fdff6cfa9ed9cc911c842a5d2395f209ec621ef1239d46810e9e495809d3ae09',
'nekohtml:xercesMinimal:1.9.6.2:xercesMinimal-1.9.6.2.jar:95b8b357d19f63797dd7d67622fd3f18374d64acbc6584faba1c7759a31e8438',
'net.bytebuddy:byte-buddy-agent:1.6.14:byte-buddy-agent-1.6.14.jar:c141a2d6809c3eeff4a43d25992826abccebdd4b793af3e7a5f346e88ae73a33',
'net.bytebuddy:byte-buddy:1.6.14:byte-buddy-1.6.14.jar:917758b3c651e278a15a029ba1d42dbf802d8b0e1fe2aa4b81c5750c64f461c1',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
'org.apache.maven.wagon:wagon-file:1.0-beta-6:wagon-file-1.0-beta-6.jar:7298feeb36ff14dd933c38e62585fb9973fea32fb3c4bc5379428cb1aac5dd3c',
'org.apache.maven.wagon:wagon-http-lightweight:1.0-beta-6:wagon-http-lightweight-1.0-beta-6.jar:be214032de23c6b520b79c1ccdb160948e0c67ed7c11984b7ec4ca5537867b4e',
'org.apache.maven.wagon:wagon-http-shared:1.0-beta-6:wagon-http-shared-1.0-beta-6.jar:f095c882716d49269a806685dcb256fa6a36389b2713ac56bb758bf8693565a2',
'org.apache.maven.wagon:wagon-provider-api:1.0-beta-6:wagon-provider-api-1.0-beta-6.jar:e116f32edcb77067289a3148143f2c0c97b27cf9a1342f8108ee37dec4868861',
'org.apache.maven:maven-ant-tasks:2.1.3:maven-ant-tasks-2.1.3.jar:f16b5ea711dfe0323454b880180aa832420ec039936e4aa75fb978748634808a',
'org.apache.maven:maven-artifact-manager:2.2.1:maven-artifact-manager-2.2.1.jar:d1e247c4ed3952385fd704ac9db2a222247cfe7d20508b4f3c76b90f857952ed',
'org.apache.maven:maven-artifact:2.2.1:maven-artifact-2.2.1.jar:d53062ffe8677a4f5e1ad3a1d1fa37ed600fab39166d39be7ed204635c5f839b',
'org.apache.maven:maven-error-diagnostics:2.2.1:maven-error-diagnostics-2.2.1.jar:b3005544708f8583e455c22b09a4940596a057108bccdadb9db4d8e048091fed',
'org.apache.maven:maven-model:2.2.1:maven-model-2.2.1.jar:153b32f474fd676ec36ad807c508885005139140fc92168bb76bf6be31f8efb8',
'org.apache.maven:maven-plugin-registry:2.2.1:maven-plugin-registry-2.2.1.jar:4ad0673155d7e0e5cf6d13689802d8d507f38e5ea00a6d2fb92aef206108213d',
'org.apache.maven:maven-profile:2.2.1:maven-profile-2.2.1.jar:ecaffef655fea6b138f0855a12f7dbb59fc0d6bffb5c1bfd31803cccb49ea08c',
'org.apache.maven:maven-project:2.2.1:maven-project-2.2.1.jar:24ddb65b7a6c3befb6267ce5f739f237c84eba99389265c30df67c3dd8396a40',
'org.apache.maven:maven-repository-metadata:2.2.1:maven-repository-metadata-2.2.1.jar:5fe283f47b0e7f7d95a4252af3fa7a0db4d8f080cd9df308608c0472b8f168a1',
'org.apache.maven:maven-settings:2.2.1:maven-settings-2.2.1.jar:9a9f556713a404e770c9dbdaed7eb086078014c989291960c76fdde6db4192f7',
'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.52:bcprov-jdk15on-1.52.jar:0dc4d181e4d347893c2ddbd2e6cd5d7287fc651c03648fa64b2341c7366b1773',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'org.codehaus.plexus:plexus-container-default:1.0-alpha-9-stable-1:plexus-container-default-1.0-alpha-9-stable-1.jar:7c758612888782ccfe376823aee7cdcc7e0cdafb097f7ef50295a0b0c3a16edf',
'org.codehaus.plexus:plexus-interpolation:1.11:plexus-interpolation-1.11.jar:fd9507feb858fa620d1b4aa4b7039fdea1a77e09d3fd28cfbddfff468d9d8c28',
'org.codehaus.plexus:plexus-utils:1.5.15:plexus-utils-1.5.15.jar:2ca121831e597b4d8f2cb22d17c5c041fc23a7777ceb6bfbdd4dfb34bbe7d997',
'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.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-integration:1.3:hamcrest-integration-1.3.jar:70f418efbb506c5155da5f9a5a33262ea08a9e4d7fea186aa9015c41a7224ac2',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
'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.mockito:mockito-core:2.8.9:mockito-core-2.8.9.jar:a2bb9b8b40d81bb02ccb84259524c0f4911f73c6577bfc7ddd940b8fc729b6e6',
'org.objenesis:objenesis:2.5:objenesis-2.5.jar:293328e1b0d31ed30bb89fca542b6c52fac00989bb0e62eb9d98d630c4dd6b7c',
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
'org.ow2.asm:asm-commons:5.0.1:asm-commons-5.0.1.jar:fb1cb7fa27d892712ced8fbf8d027eb5052ecd3999dba1ba47824357accb40e7',
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
'org.ow2.asm:asm-tree:5.0.1:asm-tree-5.0.1.jar:ff2aceed10da9930a44f6c8f81c6372d5e55eb59c4e0ea9d37f77dfd765fa9fa',
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
'org.robolectric:annotations:3.5.1:annotations-3.5.1.jar:14db0f7d2299c5400ff7764bb37b4fa80306582d8965fdf6999091723e2384ce',
'org.robolectric:junit:3.5.1:junit-3.5.1.jar:b2e81b7d5a22755f2ea76aa9bbbd4359d61c4cb9577193ccfbb8f97378ed293b',
'org.robolectric:resources:3.5.1:resources-3.5.1.jar:22a5564590c8bfd8df7efb2b0c7d9942b46a0beb59ba38899d59c1270f293b1c',
'org.robolectric:robolectric:3.5.1:robolectric-3.5.1.jar:603cf898f93b854f18021fab452aca3fe482368eeb2e720988ae82212ebcf4b6',
'org.robolectric:sandbox:3.5.1:sandbox-3.5.1.jar:beff8c3c1e840e0f7f78aadef170f347bae349f098babfc176765f499a4bcbb5',
'org.robolectric:shadowapi:3.5.1:shadowapi-3.5.1.jar:6d574f9ae0922791eb8f06979f0010997d4b862c7aec96d485ae797ddfc13278',
'org.robolectric:shadows-framework:3.5.1:shadows-framework-3.5.1.jar:597b54cc1a494799d783921c6ac04352f33e94fca8e00f299d4ca192db79e3fc',
'org.robolectric:shadows-support-v4:3.0:shadows-support-v4-3.0.jar:66bcc3257b037d72998e860d67b1bc58215b7eeac8ad860fcc3e613332d88619',
'org.robolectric:utils:3.5.1:utils-3.5.1.jar:d7d77326867e6d903156ebb18c244819b26aebe3aa82a1c57081081a0b6c4f63',
'tools.fastlane:screengrab:1.1.0:screengrab-1.1.0.aar:03ce3868ee8a0082d14e7a1de0999f91531c0cc794392688beb08ee9bc4495fd',
'uk.co.samuelwall:material-tap-target-prompt:2.8.0:material-tap-target-prompt-2.8.0.aar:ac70770c05bbc4675a1d5712c0e53d46ee4fa961b74947589fce50d8003065ec',
'xmlpull:xmlpull:1.1.3.1:xmlpull-1.1.3.1.jar:34e08ee62116071cbb69c0ed70d15a7a5b208d62798c59f2120bb8929324cb63',
'xpp3:xpp3_min:1.1.4c:xpp3_min-1.1.4c.jar:bfc90e9e32d0eab1f397fb974b5f150a815188382ac41f372a7149d5bc178008',
]
}
def getStdout = { command, defaultValue -> def getStdout = { command, defaultValue ->
def stdout = new ByteArrayOutputStream() def stdout = new ByteArrayOutputStream()
try { try {
@@ -296,7 +117,7 @@ android {
minSdkVersion 18 minSdkVersion 18
applicationIdSuffix ".screenshot" // = org.briarproject.briar.android.screenshot.debug applicationIdSuffix ".screenshot" // = org.briarproject.briar.android.screenshot.debug
} }
main { official {
dimension "version" dimension "version"
} }
} }
@@ -365,4 +186,7 @@ project.afterEvaluate {
preBuild.dependsOn.add(verifyTranslations) preBuild.dependsOn.add(verifyTranslations)
} }
tasks.withType(Test) {
// Use entropy-gathering device specified on command line, if any
systemProperty 'java.security.egd', System.getProperty('java.security.egd')
}

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.BrambleAndroidModule;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule; import org.briarproject.bramble.account.BriarAccountModule;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.login.PasswordActivityTest;
import org.briarproject.briar.android.login.SetupActivityScreenshotTest; import org.briarproject.briar.android.login.SetupActivityScreenshotTest;
import org.briarproject.briar.android.navdrawer.NavDrawerActivityTest; import org.briarproject.briar.android.navdrawer.NavDrawerActivityTest;
import org.briarproject.briar.android.settings.SettingsActivityScreenshotTest; import org.briarproject.briar.android.settings.SettingsActivityScreenshotTest;
@@ -24,7 +23,6 @@ import dagger.Component;
public interface BriarUiTestComponent extends AndroidComponent { public interface BriarUiTestComponent extends AndroidComponent {
void inject(SetupActivityScreenshotTest test); void inject(SetupActivityScreenshotTest test);
void inject(PasswordActivityTest test);
void inject(NavDrawerActivityTest test); void inject(NavDrawerActivityTest test);
void inject(SettingsActivityScreenshotTest test); void inject(SettingsActivityScreenshotTest test);

View File

@@ -4,7 +4,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/> <uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -402,5 +402,11 @@
android:theme="@android:style/Theme.NoDisplay"> android:theme="@android:style/Theme.NoDisplay">
</activity> </activity>
<activity
android:name=".android.login.UnlockActivity"
android:label="@string/lock_unlock"
android:launchMode="singleTask"
android:theme="@style/BriarTheme.NoActionBar"/>
</application> </application>
</manifest> </manifest>

View File

@@ -28,6 +28,7 @@ import org.briarproject.briar.android.login.SignInReminderReceiver;
import org.briarproject.briar.android.reporting.BriarReportSender; import org.briarproject.briar.android.reporting.BriarReportSender;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.DozeWatchdog; import org.briarproject.briar.api.android.DozeWatchdog;
import org.briarproject.briar.api.android.LockManager;
import org.briarproject.briar.api.android.ScreenFilterMonitor; import org.briarproject.briar.api.android.ScreenFilterMonitor;
import org.briarproject.briar.api.blog.BlogManager; import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogPostFactory; import org.briarproject.briar.api.blog.BlogPostFactory;
@@ -146,6 +147,8 @@ public interface AndroidComponent
AccountManager accountManager(); AccountManager accountManager();
LockManager lockManager();
void inject(SignInReminderReceiver briarService); void inject(SignInReminderReceiver briarService);
void inject(BriarService briarService); void inject(BriarService briarService);

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.android;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Application; import android.app.Application;
import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@@ -10,8 +11,8 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.support.annotation.UiThread; import android.support.annotation.UiThread;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder; import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.ContextCompat;
import org.briarproject.bramble.api.Multiset; import org.briarproject.bramble.api.Multiset;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
@@ -33,8 +34,10 @@ import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.contact.ConversationActivity; import org.briarproject.briar.android.contact.ConversationActivity;
import org.briarproject.briar.android.forum.ForumActivity; import org.briarproject.briar.android.forum.ForumActivity;
import org.briarproject.briar.android.login.SignInReminderReceiver;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity; import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.privategroup.conversation.GroupActivity; import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
import org.briarproject.briar.android.splash.SplashScreenActivity;
import org.briarproject.briar.android.util.BriarNotificationBuilder; import org.briarproject.briar.android.util.BriarNotificationBuilder;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent; import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
@@ -62,13 +65,19 @@ import javax.inject.Inject;
import static android.app.Notification.DEFAULT_LIGHTS; import static android.app.Notification.DEFAULT_LIGHTS;
import static android.app.Notification.DEFAULT_SOUND; import static android.app.Notification.DEFAULT_SOUND;
import static android.app.Notification.DEFAULT_VIBRATE; import static android.app.Notification.DEFAULT_VIBRATE;
import static android.app.Notification.VISIBILITY_SECRET;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.content.Context.NOTIFICATION_SERVICE; import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE; import static android.support.v4.app.NotificationCompat.CATEGORY_MESSAGE;
import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE;
import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL; import static android.support.v4.app.NotificationCompat.CATEGORY_SOCIAL;
import static android.support.v4.app.NotificationCompat.PRIORITY_LOW;
import static android.support.v4.app.NotificationCompat.PRIORITY_MIN;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
import static android.support.v4.content.ContextCompat.getColor;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID; import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
@@ -107,6 +116,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
private int nextRequestId = 0; private int nextRequestId = 0;
private ContactId blockedContact = null; private ContactId blockedContact = null;
private GroupId blockedGroup = null; private GroupId blockedGroup = null;
private boolean blockSignInReminder = false;
private boolean blockContacts = false, blockGroups = false; private boolean blockContacts = false, blockGroups = false;
private boolean blockForums = false, blockBlogs = false; private boolean blockForums = false, blockBlogs = false;
private boolean blockIntroductions = false; private boolean blockIntroductions = false;
@@ -166,8 +176,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
nc.setLockscreenVisibility(VISIBILITY_SECRET); nc.setLockscreenVisibility(VISIBILITY_SECRET);
nc.enableVibration(true); nc.enableVibration(true);
nc.enableLights(true); nc.enableLights(true);
nc.setLightColor( nc.setLightColor(getColor(appContext, R.color.briar_green_light));
ContextCompat.getColor(appContext, R.color.briar_green_light));
notificationManager.createNotificationChannel(nc); notificationManager.createNotificationChannel(nc);
} }
@@ -264,6 +273,47 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}); });
} }
@UiThread
@Override
public Notification getForegroundNotification() {
return getForegroundNotification(false);
}
@UiThread
private Notification getForegroundNotification(boolean locked) {
int title = locked ? R.string.lock_is_locked :
R.string.ongoing_notification_title;
int text = locked ? R.string.lock_tap_to_unlock :
R.string.ongoing_notification_text;
int icon = locked ? R.drawable.startup_lock :
R.drawable.notification_ongoing;
// Ongoing foreground notification that shows BriarService is running
NotificationCompat.Builder b =
new NotificationCompat.Builder(appContext, ONGOING_CHANNEL_ID);
b.setSmallIcon(icon);
b.setColor(getColor(appContext, R.color.briar_primary));
b.setContentTitle(appContext.getText(title));
b.setContentText(appContext.getText(text));
b.setWhen(0); // Don't show the time
b.setOngoing(true);
Intent i = new Intent(appContext, NavDrawerActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
b.setContentIntent(PendingIntent.getActivity(appContext, 0, i, 0));
if (SDK_INT >= 21) {
b.setCategory(CATEGORY_SERVICE);
b.setVisibility(VISIBILITY_SECRET);
}
b.setPriority(PRIORITY_MIN);
return b.build();
}
@UiThread
@Override
public void updateForegroundNotification(boolean locked) {
Notification n = getForegroundNotification(locked);
notificationManager.notify(ONGOING_NOTIFICATION_ID, n);
}
private void showContactNotification(ContactId c) { private void showContactNotification(ContactId c) {
androidExecutor.runOnUiThread(() -> { androidExecutor.runOnUiThread(() -> {
if (blockContacts) return; if (blockContacts) return;
@@ -612,6 +662,58 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
this::clearIntroductionSuccessNotification); this::clearIntroductionSuccessNotification);
} }
@Override
public void showSignInNotification() {
if (blockSignInReminder) return;
if (SDK_INT >= 26) {
NotificationChannel channel =
new NotificationChannel(REMINDER_CHANNEL_ID, appContext
.getString(
R.string.reminder_notification_channel_title),
IMPORTANCE_LOW);
channel.setLockscreenVisibility(
NotificationCompat.VISIBILITY_SECRET);
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder b =
new NotificationCompat.Builder(appContext, REMINDER_CHANNEL_ID);
b.setSmallIcon(R.drawable.ic_signout);
b.setColor(getColor(appContext, R.color.briar_primary));
b.setContentTitle(
appContext.getText(R.string.reminder_notification_title));
b.setContentText(
appContext.getText(R.string.reminder_notification_text));
b.setAutoCancel(true);
b.setWhen(0); // Don't show the time
b.setPriority(PRIORITY_LOW);
// Add a 'Dismiss' action
String actionTitle =
appContext.getString(R.string.reminder_notification_dismiss);
Intent i1 = new Intent(appContext, SignInReminderReceiver.class);
i1.setAction(ACTION_DISMISS_REMINDER);
PendingIntent actionIntent =
PendingIntent.getBroadcast(appContext, 0, i1, 0);
b.addAction(0, actionTitle, actionIntent);
Intent i = new Intent(appContext, SplashScreenActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
b.setContentIntent(PendingIntent.getActivity(appContext, 0, i, 0));
notificationManager.notify(REMINDER_NOTIFICATION_ID, b.build());
}
@Override
public void clearSignInNotification() {
notificationManager.cancel(REMINDER_NOTIFICATION_ID);
}
@Override
public void blockSignInNotification() {
blockSignInReminder = true;
}
@Override @Override
public void blockNotification(GroupId g) { public void blockNotification(GroupId g) {
androidExecutor.runOnUiThread((Runnable) () -> blockedGroup = g); androidExecutor.runOnUiThread((Runnable) () -> blockedGroup = g);

View File

@@ -21,15 +21,18 @@ import org.briarproject.bramble.api.reporting.DevConfig;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.Scheduler; import org.briarproject.bramble.api.system.Scheduler;
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory; import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory; import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
import org.briarproject.bramble.plugin.tor.CircumventionProvider; import org.briarproject.bramble.plugin.tor.CircumventionProvider;
import org.briarproject.bramble.plugin.tor.TorPluginFactory;
import org.briarproject.bramble.util.AndroidUtils; import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.android.account.LockManagerImpl;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.DozeWatchdog; import org.briarproject.briar.api.android.DozeWatchdog;
import org.briarproject.briar.api.android.LockManager;
import org.briarproject.briar.api.android.ScreenFilterMonitor; import org.briarproject.briar.api.android.ScreenFilterMonitor;
import java.io.File; import java.io.File;
@@ -95,14 +98,16 @@ public class AppModule {
SocketFactory torSocketFactory, BackoffFactory backoffFactory, SocketFactory torSocketFactory, BackoffFactory backoffFactory,
Application app, NetworkManager networkManager, Application app, NetworkManager networkManager,
LocationUtils locationUtils, EventBus eventBus, LocationUtils locationUtils, EventBus eventBus,
ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, Clock clock) { CircumventionProvider circumventionProvider, Clock clock) {
Context appContext = app.getApplicationContext(); Context appContext = app.getApplicationContext();
DuplexPluginFactory bluetooth = DuplexPluginFactory bluetooth =
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor, new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
appContext, random, eventBus, backoffFactory); appContext, random, eventBus, backoffFactory);
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, scheduler, DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
appContext, networkManager, locationUtils, eventBus, scheduler, appContext, networkManager, locationUtils, eventBus,
torSocketFactory, backoffFactory, circumventionProvider, clock); torSocketFactory, backoffFactory, resourceProvider,
circumventionProvider, clock);
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor, DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
eventBus, backoffFactory, appContext); eventBus, backoffFactory, appContext);
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan); Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
@@ -197,4 +202,13 @@ public class AppModule {
return dozeWatchdog; return dozeWatchdog;
} }
@Provides
@Singleton
LockManager provideLockManager(LifecycleManager lifecycleManager,
EventBus eventBus, LockManagerImpl lockManager) {
lifecycleManager.registerService(lockManager);
eventBus.addListener(lockManager);
return lockManager;
}
} }

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.android;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo; import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@@ -15,7 +16,6 @@ import android.content.ServiceConnection;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
@@ -25,6 +25,7 @@ import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.logout.HideUiActivity; import org.briarproject.briar.android.logout.HideUiActivity;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity; import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -44,8 +45,6 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION; import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.support.v4.app.NotificationCompat.CATEGORY_SERVICE;
import static android.support.v4.app.NotificationCompat.PRIORITY_MIN;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET; import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
@@ -74,6 +73,8 @@ public class BriarService extends Service {
@Nullable @Nullable
private BroadcastReceiver receiver = null; private BroadcastReceiver receiver = null;
@Inject
AndroidNotificationManager notificationManager;
@Inject @Inject
AccountManager accountManager; AccountManager accountManager;
@@ -121,24 +122,9 @@ public class BriarService extends Service {
failureChannel.setLockscreenVisibility(VISIBILITY_SECRET); failureChannel.setLockscreenVisibility(VISIBILITY_SECRET);
nm.createNotificationChannel(failureChannel); nm.createNotificationChannel(failureChannel);
} }
// Show an ongoing notification that the service is running Notification foregroundNotification =
NotificationCompat.Builder b = notificationManager.getForegroundNotification();
new NotificationCompat.Builder(this, ONGOING_CHANNEL_ID); startForeground(ONGOING_NOTIFICATION_ID, foregroundNotification);
b.setSmallIcon(R.drawable.notification_ongoing);
b.setColor(ContextCompat.getColor(this, R.color.briar_primary));
b.setContentTitle(getText(R.string.ongoing_notification_title));
b.setContentText(getText(R.string.ongoing_notification_text));
b.setWhen(0); // Don't show the time
b.setOngoing(true);
Intent i = new Intent(this, NavDrawerActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
b.setContentIntent(PendingIntent.getActivity(this, 0, i, 0));
if (SDK_INT >= 21) {
b.setCategory(CATEGORY_SERVICE);
b.setVisibility(VISIBILITY_SECRET);
}
b.setPriority(PRIORITY_MIN);
startForeground(ONGOING_NOTIFICATION_ID, b.build());
// Start the services in a background thread // Start the services in a background thread
new Thread(() -> { new Thread(() -> {
StartResult result = lifecycleManager.startServices(dbKey); StartResult result = lifecycleManager.startServices(dbKey);

View File

@@ -40,4 +40,9 @@ public interface TestingConstants {
* Feature flag for enabling the sign-in reminder in release builds. * Feature flag for enabling the sign-in reminder in release builds.
*/ */
boolean FEATURE_FLAG_SIGN_IN_REMINDER = IS_DEBUG_BUILD; boolean FEATURE_FLAG_SIGN_IN_REMINDER = IS_DEBUG_BUILD;
/**
* Feature flag for enabling the PIN lock in release builds.
*/
boolean FEATURE_FLAG_PIN_LOCK = IS_DEBUG_BUILD;
} }

View File

@@ -0,0 +1,132 @@
package org.briarproject.briar.android.account;
import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.content.Context;
import android.support.annotation.UiThread;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.LockManager;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.settings.SettingsFragment.PREF_SCREEN_LOCK;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.hasScreenLock;
@ThreadSafe
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class LockManagerImpl implements LockManager, Service, EventListener {
private static final Logger LOG =
Logger.getLogger(LockManagerImpl.class.getName());
private final Context appContext;
private final SettingsManager settingsManager;
private final AndroidNotificationManager notificationManager;
@DatabaseExecutor
private final Executor dbExecutor;
private volatile boolean locked = false;
private volatile boolean lockableSetting = false;
private final MutableLiveData<Boolean> lockable = new MutableLiveData<>();
@Inject
public LockManagerImpl(Application app, SettingsManager settingsManager,
AndroidNotificationManager notificationManager,
@DatabaseExecutor Executor dbExecutor) {
this.appContext = app.getApplicationContext();
this.settingsManager = settingsManager;
this.notificationManager = notificationManager;
this.dbExecutor = dbExecutor;
// setting this in the constructor makes #getValue() @NonNull
this.lockable.setValue(false);
}
@Override
public void startService() {
// only load the setting here, because database isn't open before
loadLockableSetting();
}
@Override
public void stopService() {
}
@Override
public LiveData<Boolean> isLockable() {
return lockable;
}
@UiThread
@Override
public void checkIfLockable() {
boolean oldValue = lockable.getValue();
boolean newValue = hasScreenLock(appContext) && lockableSetting;
if (oldValue != newValue) {
this.lockable.setValue(newValue);
}
}
@Override
public boolean isLocked() {
if (locked && !hasScreenLock(appContext)) {
lockable.postValue(false);
locked = false;
}
return locked;
}
@Override
public void setLocked(boolean locked) {
this.locked = locked;
notificationManager.updateForegroundNotification(locked);
}
@Override
public void eventOccurred(Event event) {
if (event instanceof SettingsUpdatedEvent) {
SettingsUpdatedEvent e = (SettingsUpdatedEvent) event;
String namespace = e.getNamespace();
if (namespace.equals(SETTINGS_NAMESPACE)) {
loadLockableSetting();
}
}
}
private void loadLockableSetting() {
dbExecutor.execute(() -> {
try {
Settings settings =
settingsManager.getSettings(SETTINGS_NAMESPACE);
lockableSetting = settings.getBoolean(PREF_SCREEN_LOCK, false);
boolean newValue = hasScreenLock(appContext) && lockableSetting;
lockable.postValue(newValue);
} catch (DbException e) {
logException(LOG, WARNING, e);
lockableSetting = false;
lockable.postValue(false);
}
});
}
}

View File

@@ -37,6 +37,7 @@ import org.briarproject.briar.android.login.OpenDatabaseActivity;
import org.briarproject.briar.android.login.PasswordActivity; import org.briarproject.briar.android.login.PasswordActivity;
import org.briarproject.briar.android.login.PasswordFragment; import org.briarproject.briar.android.login.PasswordFragment;
import org.briarproject.briar.android.login.SetupActivity; import org.briarproject.briar.android.login.SetupActivity;
import org.briarproject.briar.android.login.UnlockActivity;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity; import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.panic.PanicPreferencesActivity; import org.briarproject.briar.android.panic.PanicPreferencesActivity;
import org.briarproject.briar.android.panic.PanicResponderActivity; import org.briarproject.briar.android.panic.PanicResponderActivity;
@@ -163,6 +164,8 @@ public interface ActivityComponent {
void inject(StartupFailureActivity activity); void inject(StartupFailureActivity activity);
void inject(UnlockActivity activity);
// Fragments // Fragments
void inject(AuthorNameFragment fragment); void inject(AuthorNameFragment fragment);

View File

@@ -16,7 +16,9 @@ import org.briarproject.briar.android.controller.BriarController;
import org.briarproject.briar.android.controller.DbController; import org.briarproject.briar.android.controller.DbController;
import org.briarproject.briar.android.controller.handler.UiResultHandler; import org.briarproject.briar.android.controller.handler.UiResultHandler;
import org.briarproject.briar.android.login.PasswordActivity; import org.briarproject.briar.android.login.PasswordActivity;
import org.briarproject.briar.android.login.UnlockActivity;
import org.briarproject.briar.android.logout.ExitActivity; import org.briarproject.briar.android.logout.ExitActivity;
import org.briarproject.briar.api.android.LockManager;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -30,6 +32,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_UNLOCK;
import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent; import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent;
import static org.briarproject.briar.android.util.UiUtils.isSamsung7; import static org.briarproject.briar.android.util.UiUtils.isSamsung7;
@@ -44,26 +47,43 @@ public abstract class BriarActivity extends BaseActivity {
@Inject @Inject
BriarController briarController; BriarController briarController;
@Deprecated @Deprecated
@Inject @Inject
DbController dbController; DbController dbController;
@Inject
protected LockManager lockManager;
@Override @Override
protected void onActivityResult(int request, int result, Intent data) { protected void onActivityResult(int request, int result, Intent data) {
super.onActivityResult(request, result, data); super.onActivityResult(request, result, data);
if (request == REQUEST_PASSWORD) { if (request == REQUEST_PASSWORD && result == RESULT_OK) {
if (result == RESULT_OK) briarController.startAndBindService(); // PasswordActivity finishes when password was entered correctly.
else supportFinishAfterTransition(); // When back button is pressed there, it will bring itself back,
// so that we never arrive here with a result that is not OK.
briarController.startAndBindService();
} else if (request == REQUEST_UNLOCK && result != RESULT_OK) {
// We arrive here, if the user presses 'back'
// in the Keyguard unlock screen, because UnlockActivity finishes.
// If we don't finish here, isFinishing will be false in onResume()
// and we launch a new UnlockActivity causing a loop.
supportFinishAfterTransition();
// If the result is OK, we don't need to do anything here
// and can resume normally.
} }
} }
@Override @Override
public void onStart() { public void onResume() {
super.onStart(); super.onResume();
if (!briarController.accountSignedIn() && !isFinishing()) { if (!briarController.accountSignedIn()) {
Intent i = new Intent(this, PasswordActivity.class); Intent i = new Intent(this, PasswordActivity.class);
startActivityForResult(i, REQUEST_PASSWORD); startActivityForResult(i, REQUEST_PASSWORD);
} else if (lockManager.isLocked() && !isFinishing()) {
// Also check that the activity isn't finishing already.
// This is possible if finishing in onActivityResult().
// Failure to do this check would cause an UnlockActivity loop.
Intent i = new Intent(this, UnlockActivity.class);
startActivityForResult(i, REQUEST_UNLOCK);
} else if (SDK_INT >= 23) { } else if (SDK_INT >= 23) {
briarController.hasDozed(new UiResultHandler<Boolean>(this) { briarController.hasDozed(new UiResultHandler<Boolean>(this) {
@Override @Override

View File

@@ -12,5 +12,7 @@ public interface RequestCodes {
int REQUEST_PERMISSION_CAMERA = 8; int REQUEST_PERMISSION_CAMERA = 8;
int REQUEST_DOZE_WHITELISTING = 9; int REQUEST_DOZE_WHITELISTING = 9;
int REQUEST_ENABLE_BLUETOOTH = 10; int REQUEST_ENABLE_BLUETOOTH = 10;
int REQUEST_UNLOCK = 11;
int REQUEST_KEYGUARD_UNLOCK = 12;
} }

View File

@@ -17,7 +17,7 @@ import org.briarproject.briar.android.activity.ActivityComponent;
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class ErrorFragment extends BaseFragment { public class ErrorFragment extends BaseFragment {
private static final String TAG = ErrorFragment.class.getSimpleName(); private static final String TAG = ErrorFragment.class.getName();
private static final String ERROR_MSG = "errorMessage"; private static final String ERROR_MSG = "errorMessage";

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.login; package org.briarproject.briar.android.login;
import android.app.NotificationManager;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@@ -20,22 +19,23 @@ import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.controller.BriarController; import org.briarproject.briar.android.controller.BriarController;
import org.briarproject.briar.android.controller.handler.UiResultHandler; import org.briarproject.briar.android.controller.handler.UiResultHandler;
import org.briarproject.briar.android.util.UiUtils; import org.briarproject.briar.android.util.UiUtils;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import javax.inject.Inject; import javax.inject.Inject;
import static android.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_HOME;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.view.View.INVISIBLE; import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_NOTIFICATION_ID;
public class PasswordActivity extends BaseActivity { public class PasswordActivity extends BaseActivity {
@Inject @Inject
AccountManager accountManager; AccountManager accountManager;
@Inject
AndroidNotificationManager notificationManager;
@Inject @Inject
PasswordController passwordController; PasswordController passwordController;
@@ -95,10 +95,8 @@ public class PasswordActivity extends BaseActivity {
setResult(RESULT_OK); setResult(RESULT_OK);
finish(); finish();
} else { } else {
// Remove sign-in reminder notification notificationManager.blockSignInNotification();
NotificationManager nm = (NotificationManager) notificationManager.clearSignInNotification();
getSystemService(NOTIFICATION_SERVICE);
nm.cancel(REMINDER_NOTIFICATION_ID);
} }
} }
@@ -109,10 +107,9 @@ public class PasswordActivity extends BaseActivity {
@Override @Override
public void onBackPressed() { public void onBackPressed() {
// Show the home screen rather than another password prompt // Move task and activity to the background instead of showing another
Intent intent = new Intent(ACTION_MAIN); // password prompt. onActivityResult() won't be called in BriarActivity
intent.addCategory(CATEGORY_HOME); moveTaskToBack(true);
startActivity(intent);
} }
private void deleteAccount() { private void deleteAccount() {

View File

@@ -1,43 +1,29 @@
package org.briarproject.briar.android.login; package org.briarproject.briar.android.login;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.briar.R;
import org.briarproject.briar.android.AndroidComponent; import org.briarproject.briar.android.AndroidComponent;
import org.briarproject.briar.android.BriarApplication; import org.briarproject.briar.android.BriarApplication;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity; import org.briarproject.briar.api.android.AndroidNotificationManager;
import javax.inject.Inject; import javax.inject.Inject;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.ACTION_BOOT_COMPLETED; import static android.content.Intent.ACTION_BOOT_COMPLETED;
import static android.content.Intent.ACTION_MY_PACKAGE_REPLACED; import static android.content.Intent.ACTION_MY_PACKAGE_REPLACED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Build.VERSION.SDK_INT;
import static android.support.v4.app.NotificationCompat.PRIORITY_LOW;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_SIGN_IN_REMINDER; import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_SIGN_IN_REMINDER;
import static org.briarproject.briar.android.settings.SettingsFragment.NOTIFY_SIGN_IN; import static org.briarproject.briar.android.settings.SettingsFragment.NOTIFY_SIGN_IN;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.ACTION_DISMISS_REMINDER;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_NOTIFICATION_ID;
public class SignInReminderReceiver extends BroadcastReceiver { public class SignInReminderReceiver extends BroadcastReceiver {
public static final String DISMISS_REMINDER = "dismissReminder";
@Inject @Inject
AccountManager accountManager; AccountManager accountManager;
@Inject
AndroidNotificationManager notificationManager;
@Override @Override
public void onReceive(Context ctx, Intent intent) { public void onReceive(Context ctx, Intent intent) {
@@ -55,58 +41,12 @@ public class SignInReminderReceiver extends BroadcastReceiver {
!accountManager.hasDatabaseKey()) { !accountManager.hasDatabaseKey()) {
SharedPreferences prefs = app.getDefaultSharedPreferences(); SharedPreferences prefs = app.getDefaultSharedPreferences();
if (prefs.getBoolean(NOTIFY_SIGN_IN, true)) { if (prefs.getBoolean(NOTIFY_SIGN_IN, true)) {
showSignInNotification(ctx); notificationManager.showSignInNotification();
} }
} }
} else if (action.equals(DISMISS_REMINDER)) { } else if (action.equals(ACTION_DISMISS_REMINDER)) {
dismissReminder(ctx); notificationManager.clearSignInNotification();
} }
} }
private void showSignInNotification(Context ctx) {
NotificationManager nm = (NotificationManager)
ctx.getSystemService(NOTIFICATION_SERVICE);
if (nm == null) return;
if (SDK_INT >= 26) {
NotificationChannel channel =
new NotificationChannel(REMINDER_CHANNEL_ID, ctx.getString(
R.string.reminder_notification_channel_title),
IMPORTANCE_LOW);
channel.setLockscreenVisibility(VISIBILITY_SECRET);
nm.createNotificationChannel(channel);
}
NotificationCompat.Builder b =
new NotificationCompat.Builder(ctx, REMINDER_CHANNEL_ID);
b.setSmallIcon(R.drawable.ic_signout);
b.setColor(ContextCompat.getColor(ctx, R.color.briar_primary));
b.setContentTitle(ctx.getText(R.string.reminder_notification_title));
b.setContentText(ctx.getText(R.string.reminder_notification_text));
b.setAutoCancel(true);
b.setWhen(0); // Don't show the time
b.setPriority(PRIORITY_LOW);
// Add a 'Dismiss' action
String actionTitle =
ctx.getString(R.string.reminder_notification_dismiss);
Intent i1 = new Intent(ctx, SignInReminderReceiver.class);
i1.setAction(DISMISS_REMINDER);
PendingIntent actionIntent = PendingIntent.getBroadcast(ctx, 0, i1, 0);
b.addAction(0, actionTitle, actionIntent);
Intent i = new Intent(ctx, NavDrawerActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
b.setContentIntent(PendingIntent.getActivity(ctx, 0, i, 0));
nm.notify(REMINDER_NOTIFICATION_ID, b.build());
}
private void dismissReminder(Context ctx) {
NotificationManager nm = (NotificationManager)
ctx.getSystemService(NOTIFICATION_SERVICE);
if (nm == null) return;
nm.cancel(REMINDER_NOTIFICATION_ID);
}
} }

View File

@@ -0,0 +1,123 @@
package org.briarproject.briar.android.login;
import android.app.KeyguardManager;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.widget.Button;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.api.android.LockManager;
import java.util.logging.Logger;
import javax.inject.Inject;
import static android.os.Build.VERSION.SDK_INT;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_KEYGUARD_UNLOCK;
@RequiresApi(21)
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class UnlockActivity extends BaseActivity {
private static final Logger LOG =
Logger.getLogger(UnlockActivity.class.getName());
private static final String KEYGUARD_SHOWN = "keyguardShown";
@Inject
LockManager lockManager;
private boolean keyguardShown = false;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
overridePendingTransition(0, 0);
setContentView(R.layout.activity_unlock);
Button button = findViewById(R.id.unlock);
button.setOnClickListener(view -> requestKeyguardUnlock());
keyguardShown = state != null && state.getBoolean(KEYGUARD_SHOWN);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Saving whether we've shown the keyguard already is necessary
// for Android 6 when this activity gets destroyed.
//
// This will not help Android 5.
// There the system will show the keyguard once again.
// So if this activity was destroyed, the user needs to enter PIN twice.
outState.putBoolean(KEYGUARD_SHOWN, keyguardShown);
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_KEYGUARD_UNLOCK) {
if (resultCode == RESULT_OK) unlock();
else {
finish();
overridePendingTransition(0, 0);
}
}
}
@Override
protected void onResume() {
super.onResume();
// Show keyguard after onActivityResult() as been called.
// Check if app is still locked, lockable
// and not finishing (which is possible if recreated)
if (!keyguardShown && lockManager.isLocked() && !isFinishing()) {
requestKeyguardUnlock();
} else if (!lockManager.isLocked()) {
setResult(RESULT_OK);
finish();
}
}
@Override
public void onBackPressed() {
moveTaskToBack(true);
}
private void requestKeyguardUnlock() {
KeyguardManager keyguardManager =
(KeyguardManager) getSystemService(KEYGUARD_SERVICE);
if (keyguardManager == null) throw new AssertionError();
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(
SDK_INT < 23 ? getString(R.string.lock_unlock_verbose) :
getString(R.string.lock_unlock), null);
if (intent == null) {
// the user must have removed the screen lock since locked
LOG.warning("Unlocking without keyguard");
unlock();
} else {
keyguardShown = true;
startActivityForResult(intent, REQUEST_KEYGUARD_UNLOCK);
overridePendingTransition(0, 0);
}
}
private void unlock() {
lockManager.setLocked(false);
setResult(RESULT_OK);
finish();
overridePendingTransition(0, 0);
}
}

View File

@@ -7,6 +7,7 @@ import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView; import android.support.design.widget.NavigationView;
import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener; import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
@@ -136,6 +137,8 @@ public class NavDrawerActivity extends BriarActivity implements
initializeTransports(getLayoutInflater()); initializeTransports(getLayoutInflater());
transportsView.setAdapter(transportsAdapter); transportsView.setAdapter(transportsAdapter);
lockManager.isLockable().observe(this, this::setLockVisible);
if (lifecycleManager.getLifecycleState().isAfter(RUNNING)) { if (lifecycleManager.getLifecycleState().isAfter(RUNNING)) {
showSignOutFragment(); showSignOutFragment();
} else if (state == null) { } else if (state == null) {
@@ -152,6 +155,7 @@ public class NavDrawerActivity extends BriarActivity implements
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
updateTransports(); updateTransports();
lockManager.checkIfLockable();
controller.showExpiryWarning(new UiResultHandler<ExpiryWarning>(this) { controller.showExpiryWarning(new UiResultHandler<ExpiryWarning>(this) {
@Override @Override
public void onResultUi(ExpiryWarning expiry) { public void onResultUi(ExpiryWarning expiry) {
@@ -213,9 +217,15 @@ public class NavDrawerActivity extends BriarActivity implements
public boolean onNavigationItemSelected(@NonNull MenuItem item) { public boolean onNavigationItemSelected(@NonNull MenuItem item) {
drawerLayout.closeDrawer(START); drawerLayout.closeDrawer(START);
clearBackStack(); clearBackStack();
loadFragment(item.getItemId()); if (item.getItemId() == R.id.nav_btn_lock) {
// Don't display the Settings item as checked lockManager.setLocked(true);
return item.getItemId() != R.id.nav_btn_settings; ActivityCompat.finishAfterTransition(this);
return false;
} else {
loadFragment(item.getItemId());
// Don't display the Settings item as checked
return item.getItemId() != R.id.nav_btn_settings;
}
} }
@Override @Override
@@ -301,6 +311,11 @@ public class NavDrawerActivity extends BriarActivity implements
// Do nothing for now // Do nothing for now
} }
private void setLockVisible(boolean visible) {
MenuItem item = navigation.getMenu().findItem(R.id.nav_btn_lock);
if (item != null) item.setVisible(visible);
}
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
private void showExpiryWarning(ExpiryWarning expiry) { private void showExpiryWarning(ExpiryWarning expiry) {
int daysUntilExpiry = getDaysUntilExpiry(); int daysUntilExpiry = getDaysUntilExpiry();

View File

@@ -9,8 +9,8 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.ListPreference; import android.support.v7.preference.ListPreference;
import android.support.v7.preference.PreferenceFragmentCompat; import android.support.v7.preference.PreferenceFragmentCompat;
import android.text.TextUtils; import android.text.TextUtils;
@@ -37,7 +37,7 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
Logger.getLogger(PanicPreferencesFragment.class.getName()); Logger.getLogger(PanicPreferencesFragment.class.getName());
private PackageManager pm; private PackageManager pm;
private CheckBoxPreference lockPref, purgePref, uninstallPref; private SwitchPreference lockPref, purgePref, uninstallPref;
private ListPreference panicAppPref; private ListPreference panicAppPref;
@Override @Override
@@ -46,10 +46,10 @@ public class PanicPreferencesFragment extends PreferenceFragmentCompat
pm = getActivity().getPackageManager(); pm = getActivity().getPackageManager();
lockPref = (CheckBoxPreference) findPreference(KEY_LOCK); lockPref = (SwitchPreference) findPreference(KEY_LOCK);
panicAppPref = (ListPreference) findPreference(KEY_PANIC_APP); panicAppPref = (ListPreference) findPreference(KEY_PANIC_APP);
purgePref = (CheckBoxPreference) findPreference(KEY_PURGE); purgePref = (SwitchPreference) findPreference(KEY_PURGE);
uninstallPref = (CheckBoxPreference) findPreference(KEY_UNINSTALL); uninstallPref = (SwitchPreference) findPreference(KEY_UNINSTALL);
// check for connect/disconnect intents from panic trigger apps // check for connect/disconnect intents from panic trigger apps
if (PanicResponder.checkForDisconnectIntent(getActivity())) { if (PanicResponder.checkForDisconnectIntent(getActivity())) {

View File

@@ -10,9 +10,9 @@ import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import android.support.v14.preference.SwitchPreference;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v4.text.TextUtilsCompat; import android.support.v4.text.TextUtilsCompat;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.ListPreference; import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat; import android.support.v7.preference.PreferenceFragmentCompat;
@@ -82,10 +82,12 @@ import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.bramble.util.StringUtils.join; import static org.briarproject.bramble.util.StringUtils.join;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_DARK_THEME; import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_DARK_THEME;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_PIN_LOCK;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_SIGN_IN_REMINDER; import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_SIGN_IN_REMINDER;
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD; import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE;
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_SIGN_OUT; import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_SIGN_OUT;
import static org.briarproject.briar.android.util.UiUtils.hasScreenLock;
import static org.briarproject.briar.api.android.AndroidNotificationManager.BLOG_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.BLOG_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.CONTACT_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.CONTACT_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FORUM_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.FORUM_CHANNEL_ID;
@@ -109,6 +111,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
public static final String BT_NAMESPACE = BluetoothConstants.ID.getString(); public static final String BT_NAMESPACE = BluetoothConstants.ID.getString();
public static final String TOR_NAMESPACE = TorConstants.ID.getString(); public static final String TOR_NAMESPACE = TorConstants.ID.getString();
public static final String LANGUAGE = "pref_key_language"; public static final String LANGUAGE = "pref_key_language";
public static final String PREF_SCREEN_LOCK = "pref_key_lock";
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in"; public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
public static final String TOR_LOCATION = "pref_key_tor_location"; public static final String TOR_LOCATION = "pref_key_tor_location";
@@ -119,14 +122,14 @@ public class SettingsFragment extends PreferenceFragmentCompat
private ListPreference language; private ListPreference language;
private ListPreference enableBluetooth; private ListPreference enableBluetooth;
private ListPreference torNetwork; private ListPreference torNetwork;
private CheckBoxPreference torBlocked; private SwitchPreference torBlocked;
private CheckBoxPreference notifyPrivateMessages; private SwitchPreference screenLock;
private CheckBoxPreference notifyGroupMessages; private SwitchPreference notifyPrivateMessages;
private CheckBoxPreference notifyForumPosts; private SwitchPreference notifyGroupMessages;
private CheckBoxPreference notifyBlogPosts; private SwitchPreference notifyForumPosts;
private CheckBoxPreference notifyVibration; private SwitchPreference notifyBlogPosts;
private CheckBoxPreference notifyLockscreen; private SwitchPreference notifyVibration;
private SwitchPreference notifyLockscreen;
private Preference notifySound; private Preference notifySound;
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@@ -158,26 +161,25 @@ public class SettingsFragment extends PreferenceFragmentCompat
(ListPreference) findPreference("pref_key_theme"); (ListPreference) findPreference("pref_key_theme");
enableBluetooth = (ListPreference) findPreference("pref_key_bluetooth"); enableBluetooth = (ListPreference) findPreference("pref_key_bluetooth");
torNetwork = (ListPreference) findPreference("pref_key_tor_network"); torNetwork = (ListPreference) findPreference("pref_key_tor_network");
torBlocked = (CheckBoxPreference) findPreference(TOR_LOCATION); torBlocked = (SwitchPreference) findPreference(TOR_LOCATION);
setBlockedCountries(); setBlockedCountries();
CheckBoxPreference notifySignIn = SwitchPreference notifySignIn =
(CheckBoxPreference) findPreference(NOTIFY_SIGN_IN); (SwitchPreference) findPreference(NOTIFY_SIGN_IN);
notifyPrivateMessages = (CheckBoxPreference) findPreference( screenLock = (SwitchPreference) findPreference(PREF_SCREEN_LOCK);
notifyPrivateMessages = (SwitchPreference) findPreference(
"pref_key_notify_private_messages"); "pref_key_notify_private_messages");
notifyGroupMessages = (CheckBoxPreference) findPreference( notifyGroupMessages = (SwitchPreference) findPreference(
"pref_key_notify_group_messages"); "pref_key_notify_group_messages");
notifyForumPosts = (CheckBoxPreference) findPreference( notifyForumPosts = (SwitchPreference) findPreference(
"pref_key_notify_forum_posts"); "pref_key_notify_forum_posts");
notifyBlogPosts = (CheckBoxPreference) findPreference( notifyBlogPosts = (SwitchPreference) findPreference(
"pref_key_notify_blog_posts"); "pref_key_notify_blog_posts");
notifyVibration = (CheckBoxPreference) findPreference( notifyVibration = (SwitchPreference) findPreference(
"pref_key_notify_vibration"); "pref_key_notify_vibration");
notifyLockscreen = (CheckBoxPreference) findPreference( notifyLockscreen = (SwitchPreference) findPreference(
"pref_key_notify_lock_screen"); "pref_key_notify_lock_screen");
notifySound = findPreference("pref_key_notify_sound"); notifySound = findPreference("pref_key_notify_sound");
setSettingsEnabled(false);
language.setOnPreferenceChangeListener(this); language.setOnPreferenceChangeListener(this);
theme.setOnPreferenceChangeListener((preference, newValue) -> { theme.setOnPreferenceChangeListener((preference, newValue) -> {
if (getActivity() != null) { if (getActivity() != null) {
@@ -200,6 +202,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
enableBluetooth.setOnPreferenceChangeListener(this); enableBluetooth.setOnPreferenceChangeListener(this);
torNetwork.setOnPreferenceChangeListener(this); torNetwork.setOnPreferenceChangeListener(this);
torBlocked.setOnPreferenceChangeListener(this); torBlocked.setOnPreferenceChangeListener(this);
screenLock.setOnPreferenceChangeListener(this);
if (SDK_INT >= 21) { if (SDK_INT >= 21) {
notifyLockscreen.setVisible(true); notifyLockscreen.setVisible(true);
notifyLockscreen.setOnPreferenceChangeListener(this); notifyLockscreen.setOnPreferenceChangeListener(this);
@@ -220,6 +223,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
} else { } else {
theme.setVisible(FEATURE_FLAG_DARK_THEME); theme.setVisible(FEATURE_FLAG_DARK_THEME);
notifySignIn.setVisible(FEATURE_FLAG_SIGN_IN_REMINDER); notifySignIn.setVisible(FEATURE_FLAG_SIGN_IN_REMINDER);
screenLock.setVisible(FEATURE_FLAG_PIN_LOCK);
findPreference("pref_key_explode").setVisible(false); findPreference("pref_key_explode").setVisible(false);
findPreference("pref_key_test_data").setVisible(false); findPreference("pref_key_test_data").setVisible(false);
@@ -229,7 +233,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
testing.setVisible(false); testing.setVisible(false);
} }
loadSettings();
} }
@Override @Override
@@ -246,6 +249,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
eventBus.addListener(this); eventBus.addListener(this);
setSettingsEnabled(false);
loadSettings();
} }
@Override @Override
@@ -300,8 +305,26 @@ public class SettingsFragment extends PreferenceFragmentCompat
} }
private void setBlockedCountries() { private void setBlockedCountries() {
List<String> countries = new ArrayList<>(asList(BLOCKED)); List<String> countryCodes = new ArrayList<>(asList(BLOCKED));
countries.removeAll(asList(BRIDGES)); countryCodes.removeAll(asList(BRIDGES));
// Look up country names in the user's chosen language if available
Locale[] locales = Locale.getAvailableLocales();
List<String> countries = new ArrayList<>(countryCodes.size());
for (String countryCode : countryCodes) {
boolean found = false;
for (Locale locale : locales) {
if (locale.getCountry().equalsIgnoreCase(countryCode)) {
countries.add(locale.getDisplayCountry());
found = true;
break;
}
}
if (!found) {
if (LOG.isLoggable(INFO))
LOG.info("No locale for " + countryCode);
countries.add(countryCode);
}
}
Collections.sort(countries); Collections.sort(countries);
String format = getString(R.string.tor_location_setting_hint_format); String format = getString(R.string.tor_location_setting_hint_format);
torBlocked.setSummary(String.format(format, join(countries, ", "))); torBlocked.setSummary(String.format(format, join(countries, ", ")));
@@ -336,6 +359,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
enableBluetooth.setValue(Boolean.toString(btSetting)); enableBluetooth.setValue(Boolean.toString(btSetting));
torNetwork.setValue(Integer.toString(torNetworkSetting)); torNetwork.setValue(Integer.toString(torNetworkSetting));
torBlocked.setChecked(torBlockedSetting); torBlocked.setChecked(torBlockedSetting);
displayScreenLockSetting();
if (SDK_INT < 26) { if (SDK_INT < 26) {
notifyPrivateMessages.setChecked(settings.getBoolean( notifyPrivateMessages.setChecked(settings.getBoolean(
@@ -393,9 +417,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
// preferences not needed here, because handled by SharedPreferences: // preferences not needed here, because handled by SharedPreferences:
// - pref_key_theme // - pref_key_theme
// - pref_key_notify_sign_in // - pref_key_notify_sign_in
// preferences partly needed here, because they have their own logic
// - pref_key_lock (screenLock -> displayScreenLockSetting())
enableBluetooth.setEnabled(enabled); enableBluetooth.setEnabled(enabled);
torNetwork.setEnabled(enabled); torNetwork.setEnabled(enabled);
torBlocked.setEnabled(enabled); torBlocked.setEnabled(enabled);
if (!enabled) screenLock.setEnabled(false);
notifyPrivateMessages.setEnabled(enabled); notifyPrivateMessages.setEnabled(enabled);
notifyGroupMessages.setEnabled(enabled); notifyGroupMessages.setEnabled(enabled);
notifyForumPosts.setEnabled(enabled); notifyForumPosts.setEnabled(enabled);
@@ -405,8 +432,25 @@ public class SettingsFragment extends PreferenceFragmentCompat
notifySound.setEnabled(enabled); notifySound.setEnabled(enabled);
} }
private void displayScreenLockSetting() {
if (SDK_INT < 21) {
screenLock.setVisible(false);
} else {
if (getActivity() != null && hasScreenLock(getActivity())) {
screenLock.setEnabled(true);
screenLock.setChecked(
settings.getBoolean(PREF_SCREEN_LOCK, false));
screenLock.setSummary(R.string.pref_lock_summary);
} else {
screenLock.setEnabled(false);
screenLock.setChecked(false);
screenLock.setSummary(R.string.pref_lock_disabled_summary);
}
}
}
@TargetApi(26) @TargetApi(26)
private void setupNotificationPreference(CheckBoxPreference pref, private void setupNotificationPreference(SwitchPreference pref,
String channelId, @StringRes int summary) { String channelId, @StringRes int summary) {
pref.setWidgetLayoutResource(0); pref.setWidgetLayoutResource(0);
pref.setSummary(summary); pref.setSummary(summary);
@@ -460,6 +504,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
} else if (preference == torBlocked) { } else if (preference == torBlocked) {
boolean torBlockedSetting = (Boolean) newValue; boolean torBlockedSetting = (Boolean) newValue;
storeTorBlockedSetting(torBlockedSetting); storeTorBlockedSetting(torBlockedSetting);
} else if (preference == screenLock) {
Settings s = new Settings();
s.putBoolean(PREF_SCREEN_LOCK, (Boolean) newValue);
storeSettings(s);
} else if (preference == notifyPrivateMessages) { } else if (preference == notifyPrivateMessages) {
Settings s = new Settings(); Settings s = new Settings();
s.putBoolean(PREF_NOTIFY_PRIVATE, (Boolean) newValue); s.putBoolean(PREF_NOTIFY_PRIVATE, (Boolean) newValue);

View File

@@ -14,6 +14,8 @@ import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity; import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.login.OpenDatabaseActivity; import org.briarproject.briar.android.login.OpenDatabaseActivity;
import org.briarproject.briar.android.login.SetupActivity; import org.briarproject.briar.android.login.SetupActivity;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.api.android.LockManager;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -29,6 +31,8 @@ public class SplashScreenActivity extends BaseActivity {
@Inject @Inject
protected AccountManager accountManager; protected AccountManager accountManager;
@Inject @Inject
protected LockManager lockManager;
@Inject
protected AndroidExecutor androidExecutor; protected AndroidExecutor androidExecutor;
@Override @Override
@@ -44,7 +48,16 @@ public class SplashScreenActivity extends BaseActivity {
setContentView(R.layout.splash); setContentView(R.layout.splash);
if (accountManager.hasDatabaseKey()) { if (accountManager.hasDatabaseKey()) {
startActivity(new Intent(this, OpenDatabaseActivity.class)); Intent i;
if (lockManager.isLocked()) {
// The database needs to be opened for the app to be locked.
// Start main activity right away. It will open UnlockActivity.
// Otherwise, we would end up with two screen unlock inputs.
i = new Intent(this, NavDrawerActivity.class);
} else {
i = new Intent(this, OpenDatabaseActivity.class);
}
startActivity(i);
finish(); finish();
} else { } else {
new Handler().postDelayed(() -> { new Handler().postDelayed(() -> {

View File

@@ -2,6 +2,7 @@ package org.briarproject.briar.android.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnClickListener;
import android.content.Intent; import android.content.Intent;
@@ -36,6 +37,7 @@ import org.briarproject.briar.android.widget.LinkDialogFragment;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static android.content.Context.KEYGUARD_SERVICE;
import static android.content.Context.POWER_SERVICE; import static android.content.Context.POWER_SERVICE;
import static android.content.Intent.CATEGORY_DEFAULT; import static android.content.Intent.CATEGORY_DEFAULT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -229,4 +231,15 @@ public class UiUtils {
return ContextCompat.getColor(ctx, color); return ContextCompat.getColor(ctx, color);
} }
public static boolean hasScreenLock(Context ctx) {
if (SDK_INT < 21) return false;
KeyguardManager keyguardManager =
(KeyguardManager) ctx.getSystemService(KEYGUARD_SERVICE);
if (keyguardManager == null) return false;
// check if there's a lock mechanism we can use
// first one is true if SIM card is locked, so use second if available
return (SDK_INT < 23 && keyguardManager.isKeyguardSecure()) ||
(SDK_INT >= 23 && keyguardManager.isDeviceSecure());
}
} }

View File

@@ -1,5 +1,7 @@
package org.briarproject.briar.api.android; package org.briarproject.briar.api.android;
import android.app.Notification;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -49,6 +51,13 @@ public interface AndroidNotificationManager {
String BLOG_URI = "content://org.briarproject.briar/blog"; String BLOG_URI = "content://org.briarproject.briar/blog";
String INTRODUCTION_URI = "content://org.briarproject.briar/introduction"; String INTRODUCTION_URI = "content://org.briarproject.briar/introduction";
// Actions for pending intents
String ACTION_DISMISS_REMINDER = "dismissReminder";
Notification getForegroundNotification();
void updateForegroundNotification(boolean locked);
void clearContactNotification(ContactId c); void clearContactNotification(ContactId c);
void clearAllContactNotifications(); void clearAllContactNotifications();
@@ -67,6 +76,12 @@ public interface AndroidNotificationManager {
void clearAllIntroductionNotifications(); void clearAllIntroductionNotifications();
void showSignInNotification();
void clearSignInNotification();
void blockSignInNotification();
void blockContactNotification(ContactId c); void blockContactNotification(ContactId c);
void unblockContactNotification(ContactId c); void unblockContactNotification(ContactId c);

View File

@@ -0,0 +1,33 @@
package org.briarproject.briar.api.android;
import android.arch.lifecycle.LiveData;
import android.support.annotation.UiThread;
public interface LockManager {
/**
* Returns an observable LiveData to indicate whether the app can be locked.
*/
LiveData<Boolean> isLockable();
/**
* Updates the LiveData returned by {@link #isLockable()}.
* It checks whether a device screen lock is available and
* whether the app setting is checked.
*/
@UiThread
void checkIfLockable();
/**
* Returns true if app is currently locked, false otherwise.
* If the device's screen lock was removed while the app was locked,
* calling this will unlock the app automatically.
*/
boolean isLocked();
/**
* Locks the app if true is passed, otherwise unlocks the app.
*/
void setLocked(boolean locked);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
android:bottomRightRadius="@dimen/message_bubble_radius_big"
android:topLeftRadius="@dimen/message_bubble_radius_small"
android:topRightRadius="@dimen/message_bubble_radius_big"/>
<padding
android:bottom="@dimen/message_bubble_padding_bottom"
android:left="@dimen/message_bubble_padding_sides"
android:right="@dimen/message_bubble_padding_sides"
android:top="@dimen/message_bubble_padding_top"/>
<solid
android:color="@color/msg_in"/>
</shape>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke android:width="1dp" android:color="@color/msg_border"/>
<corners
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
android:bottomRightRadius="@dimen/message_bubble_radius_big"
android:topLeftRadius="@dimen/message_bubble_radius_small"
android:topRightRadius="@dimen/message_bubble_radius_big"/>
</shape>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="@dimen/message_bubble_radius_small"
android:topRightRadius="@dimen/message_bubble_radius_big"/>
<padding
android:bottom="@dimen/message_bubble_padding_top"
android:left="@dimen/message_bubble_padding_sides"
android:right="@dimen/message_bubble_padding_sides"
android:top="@dimen/message_bubble_padding_top"/>
<solid
android:color="@color/msg_in"/>
</shape>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
android:bottomRightRadius="@dimen/message_bubble_radius_big"
android:topLeftRadius="@dimen/message_bubble_radius_big"
android:topRightRadius="@dimen/message_bubble_radius_small"/>
<padding
android:bottom="@dimen/message_bubble_padding_bottom"
android:left="@dimen/message_bubble_padding_sides"
android:right="@dimen/message_bubble_padding_sides"
android:top="@dimen/message_bubble_padding_top"/>
<solid
android:color="@color/msg_out"/>
</shape>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="@dimen/message_bubble_radius_big"
android:topRightRadius="@dimen/message_bubble_radius_small"/>
<padding
android:bottom="@dimen/message_bubble_padding_top"
android:left="@dimen/message_bubble_padding_sides"
android:right="@dimen/message_bubble_padding_sides"
android:top="@dimen/message_bubble_padding_top"/>
<solid
android:color="@color/msg_out"/>
</shape>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
android:bottomRightRadius="@dimen/message_bubble_radius_big"
android:topLeftRadius="@dimen/message_bubble_radius_small"
android:topRightRadius="@dimen/message_bubble_radius_big"/>
<padding
android:bottom="@dimen/message_bubble_padding_bottom"
android:left="@dimen/message_bubble_padding_sides"
android:right="@dimen/message_bubble_padding_sides"
android:top="@dimen/message_bubble_padding_top"/>
<solid
android:color="@color/notice_in"/>
</shape>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
android:bottomRightRadius="@dimen/message_bubble_radius_big"
android:topLeftRadius="0dp"
android:topRightRadius="0dp"/>
<padding
android:bottom="@dimen/message_bubble_padding_bottom"
android:left="@dimen/message_bubble_padding_sides"
android:right="@dimen/message_bubble_padding_sides"
android:top="@dimen/message_bubble_padding_bottom"/>
<solid
android:color="@color/notice_in"/>
</shape>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
android:bottomRightRadius="@dimen/message_bubble_radius_big"
android:topLeftRadius="@dimen/message_bubble_radius_big"
android:topRightRadius="@dimen/message_bubble_radius_small"/>
<padding
android:bottom="@dimen/message_bubble_padding_bottom"
android:left="@dimen/message_bubble_padding_sides"
android:right="@dimen/message_bubble_padding_sides"
android:top="@dimen/message_bubble_padding_top"/>
<solid
android:color="@color/notice_out"/>
</shape>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="@dimen/message_bubble_radius_big"
android:bottomRightRadius="@dimen/message_bubble_radius_big"
android:topLeftRadius="0dp"
android:topRightRadius="0dp"/>
<padding
android:bottom="@dimen/message_bubble_padding_bottom"
android:left="@dimen/message_bubble_padding_sides"
android:right="@dimen/message_bubble_padding_sides"
android:top="@dimen/message_bubble_padding_bottom"/>
<solid
android:color="@color/notice_out"/>
</shape>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".android.login.UnlockActivity">
<android.support.v7.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_margin="@dimen/margin_large"
android:src="@drawable/splash_screen"
app:layout_constraintBottom_toTopOf="@+id/is_locked"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread"
app:tint="?attr/colorControlNormal"/>
<TextView
android:id="@+id/is_locked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_large"
android:gravity="center"
android:text="@string/lock_is_locked"
android:textSize="@dimen/text_size_xlarge"
app:layout_constraintBottom_toTopOf="@+id/unlock"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image"
app:layout_constraintVertical_chainStyle="spread"/>
<Button
android:id="@+id/unlock"
style="@style/BriarButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_large"
android:text="@string/lock_unlock"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</android.support.constraint.ConstraintLayout>

View File

@@ -5,12 +5,9 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/message_bubble_margin"
android:layout_marginLeft="@dimen/message_bubble_margin_tail" android:layout_marginLeft="@dimen/message_bubble_margin_tail"
android:layout_marginRight="@dimen/message_bubble_margin_non_tail" android:layout_marginRight="@dimen/message_bubble_margin_non_tail"
android:layout_marginTop="@dimen/message_bubble_margin"
android:background="@drawable/msg_in" android:background="@drawable/msg_in"
android:elevation="@dimen/message_bubble_elevation"
android:orientation="vertical"> android:orientation="vertical">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView <org.thoughtcrime.securesms.components.emoji.EmojiTextView
@@ -28,6 +25,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="right|end" android:layout_gravity="right|end"
android:layout_marginTop="@dimen/message_bubble_timestamp_margin" android:layout_marginTop="@dimen/message_bubble_timestamp_margin"
android:textColor="?android:attr/textColorSecondary"
tools:text="Dec 24, 13:37"/> tools:text="Dec 24, 13:37"/>
</LinearLayout> </LinearLayout>

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