From a2d099ea17cca15974c19f91022dc65288fc4891 Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Fri, 28 Feb 2014 23:44:35 +0000 Subject: [PATCH] Added debugging screen to alpha and beta builds. Dev task #73. --- briar-android/AndroidManifest.xml | 8 + .../res/drawable-hdpi/action_help.png | Bin 0 -> 1544 bytes .../res/drawable-hdpi/social_share.png | Bin 0 -> 1695 bytes .../res/drawable-mdpi/action_help.png | Bin 0 -> 1318 bytes .../res/drawable-mdpi/social_share.png | Bin 0 -> 1394 bytes .../res/drawable-xhdpi/action_help.png | Bin 0 -> 1796 bytes .../res/drawable-xhdpi/social_share.png | Bin 0 -> 1989 bytes briar-android/res/values/color.xml | 1 + briar-android/res/values/strings.xml | 2 +- .../android/DashboardActivity.java | 25 +- .../briarproject/android/TestingActivity.java | 347 ++++++++++++++++++ .../plugins/droidtooth/DroidtoothPlugin.java | 15 +- .../briarproject/plugins/tor/TorPlugin.java | 7 +- .../org/briarproject/api/plugins/Plugin.java | 3 + .../api/plugins/PluginManager.java | 7 + .../plugins/PluginManagerImpl.java | 18 +- .../briarproject/plugins/file/FilePlugin.java | 4 + .../briarproject/plugins/tcp/TcpPlugin.java | 4 + .../plugins/bluetooth/BluetoothPlugin.java | 4 + .../plugins/modem/ModemPlugin.java | 38 +- 20 files changed, 440 insertions(+), 43 deletions(-) create mode 100644 briar-android/res/drawable-hdpi/action_help.png create mode 100644 briar-android/res/drawable-hdpi/social_share.png create mode 100644 briar-android/res/drawable-mdpi/action_help.png create mode 100644 briar-android/res/drawable-mdpi/social_share.png create mode 100644 briar-android/res/drawable-xhdpi/action_help.png create mode 100644 briar-android/res/drawable-xhdpi/social_share.png create mode 100644 briar-android/src/org/briarproject/android/TestingActivity.java diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml index ab787cf379..b9119cccb8 100644 --- a/briar-android/AndroidManifest.xml +++ b/briar-android/AndroidManifest.xml @@ -12,6 +12,9 @@ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.VIBRATE" /> + <!-- FIXME: Only needed for alpha and beta builds --> + <uses-permission android:name="android.permission.READ_LOGS" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:theme="@style/LightTheme" @@ -54,6 +57,11 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity + android:name=".android.TestingActivity" + android:logo="@drawable/logo" + android:label="@string/app_name" > + </activity> <activity android:name=".android.contact.ContactListActivity" android:logo="@drawable/logo" diff --git a/briar-android/res/drawable-hdpi/action_help.png b/briar-android/res/drawable-hdpi/action_help.png new file mode 100644 index 0000000000000000000000000000000000000000..459bed76c5b9f546541383271a6c9b9ff9943093 GIT binary patch literal 1544 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W~g9hqGxDg zU}<8hqhMrUXrOOsq;FuZYiM9)YHnp<r~m~@K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s0<RzFwUtj!6b93RUi%Wu15$?rmaB)aw zL8^XGYH@yPQ8F;%(v(3~6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fKRL@YsH!(Rg z4<rKC;p=PVnO9trn3tUD>0+w{G(#^lGsVipz|h&;z|zRn$-u?X(ACh=#L&{!#L3yw z&D7A`#K{n**Cju>G&eP`1g19ytk=TG!rZ_Nr(RHE$SnZc?2=lPS(cjOR+OKs0QR(1 zCT_PF;4}}aHwCL(!2U4AsaGH97=2LGB1JV!2$+6AOnAZta^OinH4m8Hi+~AxLcu## z1_q`oPZ!6Kid%1H-uD&>6ggg=7Jk~~VBDl$IW3hy&m~7E)o6b3f3ekp>yY^WNpe+u z@<-AqPMF8_Wug28X_qI?ES+j=1dfWmj9P14$6q6^#~yoW=FOSj-w(B?zQ1?Z@_zNX zozKs#5pPR8_w1o1qhEvY0~QO$m7E$=y{cAm$1u4TusyMiXOBN9b<=o%h~D)6TxZ2L z-wy{3Bv_|Anp-fQnfviaop?^u^9P|aavfR^q-HRP|A?-4WGLhNY;oO=;cr6U{mw1b zfyXQ)5<K2~+8XI|D!qQkH?<wI?Y|fIq%SBtptrqo@&e%!nFlZ3Ebb=VSSseU`hoD_ zg?@*RZYcdEJ7?MSt~-B^O$e}NUDw>7$vI&{BwM(H=$Zy|o6J|otUTZRPVnfQVEX*> zmxiA52Zj~=`(!sgQ?EEx@Uh2cBJT^&=!TXvm+aU4J}A8WuD}CL|E)Hi{YG6rZvtZX zXEir4^`G4%r0_X@lb%D*p3^M<)~<`~j+)5LDXstaf~>)z7{lz=mdi>%=7cgnKOoY7 za+cA)=HqXjZtV>)e!To(Wa^&tZuy#hb{d+DNe@(BgdQ_rXUaeC$jpR7{>%@*rhKe? z_f4ll_W99AcC9sPISZ2PJP!R(VcB9_@+vFOl=Jaq4#j@U2hyyo53DmuZ*Gw34xL?i z|MlzY2RhsnlD-C1I_%k$+s$CO>(Z&?T5I39tv$(jbBg0*zij534XzC)8Q%|tKHk2x zVK1xks)eUhIPNkeuVJ=M=`T(;dvd^4N@m4!en$JvN}Y$*T=hOPY3U^0D#(0hmMid~ zsn%aSKdQy=+}<q@MJB29^v^i6ch2oaANNlZc<^swA=4ZN^#hzg_Org>Heh(<y|q2M T-w{}9Gcb6%`njxgN@xNAO}|8u literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-hdpi/social_share.png b/briar-android/res/drawable-hdpi/social_share.png new file mode 100644 index 0000000000000000000000000000000000000000..47ae186749df92bbbe77f860ce657d3edce27765 GIT binary patch literal 1695 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W~g9hqGxDg zU}<8hqhMrUXrOOsq;FuZYiM9)YHnp<r~m~@K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s0<RzFwUtj!6b93RUi%Wu15$?rmaB)aw zL8^XGYH@yPQ8F;%(v(3~6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fKRL@YsH!(Rg z4<rKC;p=PVnO9trn3tUD>0+w{G(#^lGsVi((a6=+z{J?p$-u?X(ACh=#L&{!#L3yw z&D7A`#K{n**Cju>G&eP`1g19yq1ObbUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnqfX zG!Lpb1-Dy_aO%|uIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1z&RAG31<Wsko-U3d z6}R5Z^v)0t6lqh>Ob*hqyVd$&@e0?F6+aZ5Vmma%%tHl4yS%3><;9deKG$0k{QVu* z(Om)}@(UIugmMIWEbQv{SR1OdNObi{laoK>f3UYLG%oKs`Q+HS#{Nku9`Ebl?|lB} zyINZ0w2Nm1&1cytF-~k)s<+_k`@<zxvd1K*HRf%YwLbk|^@ard2`5ul2@5!_VR1hw zH{ntB{sX}U(r5l(=DK2Ob+GbW9pepN&#*@pH@Mmk^2dHZkjWR9wv$I|2}@nm+XpHc zmje%|U0|;JZKFK@Evt2@=!8c-)vZfHgmSJ0HiXQJXn39^vT$yLMRBaElh?~0zt9Zj z7wpy|FO%0#`qIoP%d&>m-9bO%+@EP}SI-$v5tH1*xvsgtSL6aCUo&$~l+gVH$_3M> zz7VNyn(HUpCC#|g&D3b-)8-W3`;%||W4XgT|HnOx3f8j1sVS+;4seGuuXc0be!=wm z=P%<EyQkSRervWnUhF!7b^DCV?|yK-yMFYHWs<B!Lbbnz))8w1FU7rQKIer=o_y$8 zFuDG4`C^`#C%MmDZn~_x>F#{y_ycBL!qFdQ8PDSl$bF@iAo|y1x%+MXg5t6Q;W~!$ z1CL#`yq#IzJkt@cou^s+fq$l->s-H-*fl4^8aiiiR)6q*<YRL*Ytbhi)oUM@<T1_L z%%Udx*Kyx-fgLB--Cot*@IImE?6O|%hb}gMWhzeAZepCn*j%J8;MT=9b7f}1&BYUa zt4ucOKFE>i)p=IF^YyN<mDjvxaA_~>iHco4#qz<PM+~1BY>H>@thHg@adu9v^+S{5 z%Xg}ax0)5#3xD>RTR460yT|uFY`QG=a{1hI*Nj?Ul`hEqXmLU3L!8F*=}w8JMlUag zA5^`!>*U+pT<-jZ?Vf__FIu*~JhG{CeS<XPzwIZdzP@<TD`dz25IJo}!CRaL%slt@ z-O+lbp>Te)ON^n}P3`;=QG>)E@pqO*xE1fZmAUeBeq>m#v&8dz8O#4l82{04kpA_% zLE?yFL67?WWxpE_FNoctR(AZu&(4*v{QlU_IRQ$N9u3bvx;HQ~DDj*tE_ssV52`Xe MUHx3vIVCg!0FRcDBme*a literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-mdpi/action_help.png b/briar-android/res/drawable-mdpi/action_help.png new file mode 100644 index 0000000000000000000000000000000000000000..72edd5a761481a3598974dac6d741b31ca953fb7 GIT binary patch literal 1318 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W~g9hqGxDg zU}<8hqhMrUXrOOsq;FuZYiM9)YHnp<r~m~@K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s0<RzFwUtj!6b93RUi%Wu15$?rmaB)aw zL8^XGYH@yPQ8F;%(v(3~6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fKRL@YsH!(Rg z4<rKC;p=PVnO9trn3tUD>0+w{G(#^lGsVipz{1GF+`!V*$-u?X(ACh=#L&{!#L3yw z&D7A`#K{n**Cju>G&eP`1g19yq1O?oUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnv1@ zG!Lpb1-Dx)aO%|uIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1zo?(~5$H2fi!_&nv zq~g|_>HGCr9A%D{n^(6#?s)NqOVMeKi-rhS;7e62srnwLDK1-7vU<H-Hgl<julSQy z&??`~k+*mH9$zzYAxrDcXX_^WKP$`6-=Cj$?@al*-bE))8ri5nKEaxzci{i)W=8=P z*Y90r4&wIB+6D6VB5jGgm;~-7@bqX`N*8>Ub-i+c^9CFL%6^6<!JdZl4-2maf3nhO z((H_8^v|q*AX1|hxw<NT@{C3AKJVf`Gee@0dGCx)zJroGSW^v_zwC5RV|cSf_krk| zrd3r^?7Ta;+rHRwy)iLl>gkSuCoWW%@H?$qeg><qP{4&rCPqxXj>hMjJ<sl4zw*{* z#fE3mY|UP$=G8a)7Gy>-)Nh~SaW3@-huIb@nafOW2RBUm9o3ip;8>X9tMJ!ZH*-xV z|FLH}Wt8A~z5LkfMCUinT~+7b{ye&^p=(3A+z-Wwl3fS3`egVr^loQZ_I2jr{d|47 zGdHmNtoT%T{{02Z1Gi>g@Sf8&$Axi|+JaS!!#xXr+irT<xa*ls$lc|f=VyyPcvgS5 fh%u7;hgbrGXm?!3!@v9YgGw$>S3j3^P6<r_yYJL& literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-mdpi/social_share.png b/briar-android/res/drawable-mdpi/social_share.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa52bc7d8a74739dc5e0ad9c35a006bdcbda182 GIT binary patch literal 1394 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W~g9hqGxDg zU}<8hqhMrUXrOOsq;FuZYiM9)YHnp<r~m~@K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s0<RzFwUtj!6b93RUi%Wu15$?rmaB)aw zL8^XGYH@yPQ8F;%(v(3~6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fKRL@YsH!(Rg z4<rKC;p=PVnO9trn3tUD>0+w{G(#^lGsVi((b2-i#nH^v$-u?X(ACh=#L&{!#L3yw z&D7A`#K{n**Cju>G&eP`1g19yq1POzUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dR<{_r zx*C|6;xrGcHwCL(z<P1}Lm%iEeNfaQMKw$an0`P^c)|s8;7LC<518JIfC*cxe$saa z2F53zE{-7;x86)Yt?d#hbNo49+s9LGfyqKQE0$!YDXtfq_=A7V8y%gTRMqT_$w%AP zw))(haHGP<%SWtPK#=>X?XsPZt6!~N_cHET={uFrtNkzkS!VgX`uUvq-{%A>P3%ye zo4R$$P9vsGUuVhntKTf-c4XerEM1^8%Wl5D8KY;Is07o~8hN(c34Apt;+kv>I8GhV z7M#4TInMZ-gK9y8xv&3^Ke9W{2q+v2=CM0HQFj5`mu8*0g~bOm&**h*mYK6-YPR0C zDqYzHpHAu@^jgI_rAh9>NzZK-Crwu{>u!0>8o|#0k!wSv+5;B<gz5A2*kTt*Pie5- zz{51_{V&fX#}+N7!!<%vvu`n$x%f456>y{-a6C0x;41s8gPWIyAJ`XhKC`V`OSS9g zlY=YfeJJM8Iri)Gzn7OU_`lEcewZiEaCW6ozDb9;OyS+PHMNQH9MX)*3j(jn32d8f zvSDF(^5H;cX*Jyghk|p0m;dLOCSeor_~e&jM@#lKA<jkjU&-k-@VXUB7Zm@`SbW2G z*@3w{;xUbp27G=JAz^YS9n(4|D=occa6pygHOmx%pj<b;6+Ak7xn?RpnB$$)e~P~_ z^tQQk!;Y%6&CwJ570q^KhF)t`*>&y!3;*W)>qUEmjQ;cf-`n8N$i^W2yU>O2ZR}N0 ODd_3y=d#Wzp$PyYS@Qk> literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-xhdpi/action_help.png b/briar-android/res/drawable-xhdpi/action_help.png new file mode 100644 index 0000000000000000000000000000000000000000..0e67d7c12130fd86e9c7191c236b31aebdfe890e GIT binary patch literal 1796 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m{l@EB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9<K~ zz|zE0N5ROz&_LhNNZ-I**U-Sq)ZEIzPyq^*fVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD<cE0=g99h1>$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;Np<V zf>iyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh**NZ(?$0 z9!LbN!`Ii!Gq1QLF)umQ)5TT^Xog;9W{Q=GfuXaxfrYE7lYxt&p{t>#iJ_&diIcOV zo2j9>iIX8ruS<S%X>Mv>2~2MaLa!T6y`aR9TL84#CABECEH%ZgC_h&L>}jh^+-`Bk zX&zK>3U0T!;MA)Rbc{YIYLTKECIn1BASOKF0y*%cpPC0u??u3b{ao69Eik{7dAc}; zRNQ(qJGP%YQ0AEb?cCi{mTKQf5L7z2sUy#2NAdGhtsNcPyT3BlaF*LOa&xW|i0Kp% za%9>2X;RLHkLQjpGP!Z-ZQt|xc4y7bp4rm-*5~|7%ai)I-)=Fko@e?0y0LVjjC<*) zj#Yf}VGP<0q6fGVST`_5Fj|$Doc+RSJhSKiLrVqLOEs}`+x{`!ca;0{)ymOqc5Xgn z&AQDJYgqp#*m+#3S;k=3JUxNs&y^z9D?L*a1acT_75tPEP92qbx>xB3>$_&_2aEHV zPCU8RESsP_<GANki-S(g_r;BG@@{KB{a~9PlMI{n&LgRhgnjGoE3$T#cRb&<&|74} z?m16by#80N>oUIM9el~DAzFbwsdQRp%k}kpzDcQa?P5Q3&9TA%f#%%Uw@W4;S!vX- z)UWz#O-pEk1G~I}T7hiNTA>|}_~RO$Crr5)8|I}S!CTh&G~v=={SJ@U2b5(GJ&->3 zNm0$5{~)v9zy8x*f^yA|dFJMIPT<(=vfSo@)Q@9V4Xzz{uFAZJv+qNmwchFl;p&WT z9>$MteV3j-%(Kf^zipD8pyR)5g_l_)f<;yDIHli9VSLt<Yj<3A%|4^h29~+^jea%U z5=<`r;j%qz!^De+YwAxd4-jg6w=IdaMfU(#!Gvw`A0mHEGKsyoQT~CsS>xiKw{_)l z)Bb6yg&gD9Ajz|Nhvtu#BZYo-A=mpR+?IIoB>2?s@9LcAvkPX~Pt|1dP%hbj{)x8e z;u5>_+p=!9Yc_<`{MBQfxJs*YeN(sb1)of7#-J^=>)AZ#Oy2)sB4?I<!<M7sl`2++ z)6P6^F7t3qYqIqzUmo*r-;d_%#FoVhtR0%~?GiOP+QqkVhS=0xeEK&cqSSK&)04<E zK07!9g1(yjY!P>mTBKfMQ**L}QKp|m;ME3xkCI&sj>`{C`oOd4pZ{gWeW~x}o5wO# zYCM{u_5PiU<gaBf{-kLC>CwvXlgMNediCw&JO51*zs_Dz->=WY9>Q&AcgwZGgnMCA z(fyATzb{qXbufhSSB36=Eq|ZH#+6J*q|OL0TE=B?&7oJH&oX@#!zS-PeMcvRSNvHu z>%PxbH-?Sxi&x#bKi#ij`>eXC6tVvJAl*6@y*D-vLh~kP{qmg9^~2K4d0wfL+7H*M z@=Xz^QuXT`tNzO$@@iH7w*Od;X$CmKuVDbE{{_y+?HSn^+&p)g-|%3a462trUHx3v IIVCg!0CTakTmS$7 literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-xhdpi/social_share.png b/briar-android/res/drawable-xhdpi/social_share.png new file mode 100644 index 0000000000000000000000000000000000000000..cdafd8abca1912ff47f812c38fd29994da1d7867 GIT binary patch literal 1989 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 literal 0 HcmV?d00001 diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml index b25cc18435..8b0ec7923c 100644 --- a/briar-android/res/values/color.xml +++ b/briar-android/res/values/color.xml @@ -4,6 +4,7 @@ <color name="action_bar_text">#FFFFFF</color> <color name="action_bar_background">#2D3E50</color> <color name="button_bar_background">#FFFFFF</color> + <color name="dashboard_background">#FFFFFF</color> <color name="private_message_background">#FFFFFF</color> <color name="private_message_date">#AAAAAA</color> <color name="unread_background">#FFFFFF</color> diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 338a010865..b452b23ea3 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -16,7 +16,7 @@ <string name="expiry_warning">This software has expired.\nPlease install a newer version.</string> <string name="contact_list_button">Contacts</string> <string name="forums_button">Forums</string> - <string name="synchronize_button">Synchronize</string> + <string name="testing_button">Testing</string> <string name="sign_out_button">Sign Out</string> <string name="contact_list_title">Contacts</string> <string name="no_contacts">No contacts</string> diff --git a/briar-android/src/org/briarproject/android/DashboardActivity.java b/briar-android/src/org/briarproject/android/DashboardActivity.java index f1f604f1e7..956254c4f1 100644 --- a/briar-android/src/org/briarproject/android/DashboardActivity.java +++ b/briar-android/src/org/briarproject/android/DashboardActivity.java @@ -2,7 +2,6 @@ package org.briarproject.android; import static android.view.Gravity.CENTER; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.widget.Toast.LENGTH_SHORT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH; @@ -37,7 +36,6 @@ import android.widget.GridView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; -import android.widget.Toast; public class DashboardActivity extends BriarActivity { @@ -121,20 +119,19 @@ public class DashboardActivity extends BriarActivity { }); buttons.add(forumsButton); - Button syncButton = new Button(this); - syncButton.setLayoutParams(matchMatch); - syncButton.setBackgroundResource(0); - syncButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.navigation_refresh, 0, 0); - syncButton.setText(R.string.synchronize_button); - syncButton.setOnClickListener(new OnClickListener() { + Button testingButton = new Button(this); + testingButton.setLayoutParams(matchMatch); + testingButton.setBackgroundResource(0); + testingButton.setCompoundDrawablesWithIntrinsicBounds(0, + R.drawable.action_help, 0, 0); + testingButton.setText(R.string.testing_button); + testingButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { - // FIXME: Hook this button up to an activity - Toast.makeText(DashboardActivity.this, - R.string.not_implemented_toast, LENGTH_SHORT).show(); + startActivity(new Intent(DashboardActivity.this, + TestingActivity.class)); } }); - buttons.add(syncButton); + buttons.add(testingButton); Button signOutButton = new Button(this); signOutButton.setLayoutParams(matchMatch); @@ -157,7 +154,7 @@ public class DashboardActivity extends BriarActivity { grid.setGravity(CENTER); grid.setPadding(pad, pad, pad, pad); Resources res = getResources(); - grid.setBackgroundColor(res.getColor(R.color.button_bar_background)); + grid.setBackgroundColor(res.getColor(R.color.dashboard_background)); grid.setNumColumns(2); grid.setAdapter(new BaseAdapter() { diff --git a/briar-android/src/org/briarproject/android/TestingActivity.java b/briar-android/src/org/briarproject/android/TestingActivity.java new file mode 100644 index 0000000000..0ff9381ce9 --- /dev/null +++ b/briar-android/src/org/briarproject/android/TestingActivity.java @@ -0,0 +1,347 @@ +package org.briarproject.android; + +import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE; +import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; +import static android.content.Intent.ACTION_SEND; +import static android.content.Intent.EXTRA_EMAIL; +import static android.content.Intent.EXTRA_STREAM; +import static android.content.Intent.EXTRA_SUBJECT; +import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.widget.LinearLayout.VERTICAL; +import static java.util.logging.Level.INFO; +import static java.util.logging.Level.WARNING; +import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH; +import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP; +import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Scanner; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import org.briarproject.R; +import org.briarproject.android.util.ElasticHorizontalSpace; +import org.briarproject.android.util.HorizontalBorder; +import org.briarproject.android.util.LayoutUtils; +import org.briarproject.api.TransportId; +import org.briarproject.api.android.AndroidExecutor; +import org.briarproject.api.plugins.Plugin; +import org.briarproject.api.plugins.PluginManager; +import org.briarproject.util.StringUtils; + +import android.bluetooth.BluetoothAdapter; +import android.content.Intent; +import android.content.res.Resources; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.Uri; +import android.net.wifi.WifiManager; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +public class TestingActivity extends BriarActivity implements OnClickListener { + + private static final Logger LOG = + Logger.getLogger(TestingActivity.class.getName()); + + @Inject private AndroidExecutor androidExecutor; + @Inject private PluginManager pluginManager; + private ScrollView scroll = null; + private LinearLayout status = null; + private ImageButton refresh = null, share = null; + private File temp = null; + + @Override + public void onCreate(Bundle state) { + super.onCreate(state); + + LinearLayout layout = new LinearLayout(this); + layout.setLayoutParams(MATCH_MATCH); + layout.setOrientation(VERTICAL); + layout.setGravity(CENTER_HORIZONTAL); + + scroll = new ScrollView(this); + scroll.setLayoutParams(MATCH_WRAP_1); + status = new LinearLayout(this); + status.setOrientation(VERTICAL); + status.setGravity(CENTER_HORIZONTAL); + int pad = LayoutUtils.getPadding(this); + status.setPadding(pad, pad, pad, pad); + scroll.addView(status); + layout.addView(scroll); + + layout.addView(new HorizontalBorder(this)); + + LinearLayout footer = new LinearLayout(this); + footer.setLayoutParams(MATCH_WRAP); + footer.setGravity(CENTER); + Resources res = getResources(); + footer.setBackgroundColor(res.getColor(R.color.button_bar_background)); + footer.addView(new ElasticHorizontalSpace(this)); + + refresh = new ImageButton(this); + refresh.setBackgroundResource(0); + refresh.setImageResource(R.drawable.navigation_refresh); + refresh.setOnClickListener(this); + footer.addView(refresh); + footer.addView(new ElasticHorizontalSpace(this)); + + share = new ImageButton(this); + share.setBackgroundResource(0); + share.setImageResource(R.drawable.social_share); + share.setOnClickListener(this); + footer.addView(share); + footer.addView(new ElasticHorizontalSpace(this)); + layout.addView(footer); + + setContentView(layout); + } + + @Override + public void onResume() { + super.onResume(); + refresh(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if(temp != null) temp.delete(); + } + + public void onClick(View view) { + if(view == refresh) refresh(); + else if(view == share) share(); + } + + private void refresh() { + status.removeAllViews(); + new AsyncTask<Void, Void, Map<String, String>>() { + + protected Map<String, String> doInBackground(Void... args) { + return getStatusMap(); + } + + protected void onPostExecute(Map<String, String> result) { + int pad = LayoutUtils.getPadding(TestingActivity.this); + for(Entry<String, String> e : result.entrySet()) { + TextView title = new TextView(TestingActivity.this); + title.setTextSize(18); + title.setText(e.getKey()); + status.addView(title); + TextView content = new TextView(TestingActivity.this); + content.setPadding(0, 0, 0, pad); + content.setText(e.getValue()); + status.addView(content); + } + scroll.scrollTo(0, 0); + } + }.execute(); + } + + private Map<String, String> getStatusMap() { + Map<String, String> statusMap = new LinkedHashMap<String, String>(); + // Is mobile data available? + Object o = getSystemService(CONNECTIVITY_SERVICE); + ConnectivityManager cm = (ConnectivityManager) o; + NetworkInfo mobile = cm.getNetworkInfo(TYPE_MOBILE); + boolean mobileAvailable = mobile != null && mobile.isAvailable(); + // Is mobile data enabled? + boolean mobileEnabled = false; + try { + Class<?> clazz = Class.forName(cm.getClass().getName()); + Method method = clazz.getDeclaredMethod("getMobileDataEnabled"); + method.setAccessible(true); + mobileEnabled = (Boolean) method.invoke(cm); + } catch(ClassNotFoundException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } catch(NoSuchMethodException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } catch(IllegalAccessException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } catch(IllegalArgumentException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } catch(InvocationTargetException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } + // Is mobile data connected ? + boolean mobileConnected = mobile != null && mobile.isConnected(); + + // Strings aren't loaded from resources as this activity is temporary + String mobileStatus; + if(mobileAvailable) mobileStatus = "Available, "; + else mobileStatus = "Not available, "; + if(mobileEnabled) mobileStatus += "enabled, "; + else mobileStatus += "not enabled, "; + if(mobileConnected) mobileStatus += "connected"; + else mobileStatus += "not connected"; + statusMap.put("Mobile data:", mobileStatus); + + // Is wifi available? + NetworkInfo wifi = cm.getNetworkInfo(TYPE_WIFI); + boolean wifiAvailable = wifi != null && wifi.isAvailable(); + // Is wifi enabled? + WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE); + boolean wifiEnabled = wm != null && + wm.getWifiState() == WIFI_STATE_ENABLED; + // Is wifi connected? + boolean wifiConnected = wifi != null && wifi.isConnected(); + + String wifiStatus; + if(wifiAvailable) wifiStatus = "Available, "; + else wifiStatus = "Not available, "; + if(wifiEnabled) wifiStatus += "enabled, "; + else wifiStatus += "not enabled, "; + if(wifiConnected) wifiStatus += "connected"; + else wifiStatus += "not connected"; + statusMap.put("Wi-Fi:", wifiStatus); + + // Is Bluetooth available? + BluetoothAdapter bt = null; + try { + bt = androidExecutor.call(new Callable<BluetoothAdapter>() { + public BluetoothAdapter call() throws Exception { + return BluetoothAdapter.getDefaultAdapter(); + } + }); + } catch(InterruptedException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } catch(ExecutionException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } + boolean btAvailable = bt != null; + // Is Bluetooth enabled? + boolean btEnabled = bt != null && bt.isEnabled() && + !StringUtils.isNullOrEmpty(bt.getAddress()); + // Is Bluetooth connectable? + boolean btConnectable = bt != null && + (bt.getScanMode() == SCAN_MODE_CONNECTABLE || + bt.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE); + // Is Bluetooth discoverable? + boolean btDiscoverable = bt != null && + bt.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE; + + String btStatus; + if(btAvailable) btStatus = "Available, "; + else btStatus = "Not available, "; + if(btEnabled) btStatus += "enabled, "; + else btStatus += "not enabled, "; + if(btConnectable) btStatus += "connectable, "; + else btStatus += "not connectable, "; + if(btDiscoverable) btStatus += "discoverable"; + else btStatus += "not discoverable"; + statusMap.put("Bluetooth:", btStatus); + + Plugin torPlugin = pluginManager.getPlugin(new TransportId("tor")); + boolean torPluginEnabled = torPlugin != null; + boolean torPluginRunning = torPlugin != null && torPlugin.isRunning(); + + String torPluginStatus; + if(torPluginEnabled) torPluginStatus = "Enabled, "; + else torPluginStatus = "Not enabled, "; + if(torPluginRunning) torPluginStatus += "running"; + else torPluginStatus += "not running"; + statusMap.put("Tor plugin:", torPluginStatus); + + Plugin lanPlugin = pluginManager.getPlugin(new TransportId("lan")); + boolean lanPluginEnabled = lanPlugin != null; + boolean lanPluginRunning = lanPlugin != null && lanPlugin.isRunning(); + + String lanPluginStatus; + if(lanPluginEnabled) lanPluginStatus = "Enabled, "; + else lanPluginStatus = "Not enabled, "; + if(lanPluginRunning) lanPluginStatus += "running"; + else lanPluginStatus += "not running"; + statusMap.put("LAN plugin:", lanPluginStatus); + + Plugin btPlugin = pluginManager.getPlugin(new TransportId("bt")); + boolean btPluginEnabled = btPlugin != null; + boolean btPluginRunning = btPlugin != null && btPlugin.isRunning(); + + String btPluginStatus; + if(btPluginEnabled) btPluginStatus = "Enabled, "; + else btPluginStatus = "Not enabled, "; + if(btPluginRunning) btPluginStatus += "running"; + else btPluginStatus += "not running"; + statusMap.put("Bluetooth plugin:", btPluginStatus); + + StringBuilder log = new StringBuilder(); + try { + Runtime runtime = Runtime.getRuntime(); + Process process = runtime.exec("logcat -d -s TorPlugin"); + Scanner scanner = new Scanner(process.getInputStream()); + while(scanner.hasNextLine()) { + log.append(scanner.nextLine()); + log.append('\n'); + } + scanner.close(); + } catch(IOException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } + statusMap.put("Tor log:", log.toString()); + + return Collections.unmodifiableMap(statusMap); + } + + private void share() { + new AsyncTask<Void, Void, Map<String, String>>() { + + protected Map<String, String> doInBackground(Void... args) { + return getStatusMap(); + } + + protected void onPostExecute(Map<String, String> result) { + try { + File shared = Environment.getExternalStorageDirectory(); + temp = File.createTempFile("debug", "txt", shared); + if(LOG.isLoggable(INFO)) + LOG.info("Writing to " + temp.getPath()); + PrintStream p = new PrintStream(new FileOutputStream(temp)); + for(Entry<String, String> e : result.entrySet()) { + p.println(e.getKey()); + p.println(e.getValue()); + p.println(); + } + p.flush(); + p.close(); + sendEmail(Uri.fromFile(temp)); + } catch(IOException e) { + if(LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } + } + }.execute(); + } + + private void sendEmail(Uri attachment) { + Intent i = new Intent(ACTION_SEND); + i.setType("message/rfc822"); + i.putExtra(EXTRA_EMAIL, new String[] { "debug@briarproject.org" }); + i.putExtra(EXTRA_SUBJECT, "Debugging information"); + i.putExtra(EXTRA_STREAM, attachment); + startActivity(Intent.createChooser(i, "Send to developers")); + } +} diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java index b2609f435d..4a875f5fb6 100644 --- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java +++ b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java @@ -68,6 +68,7 @@ class DroidtoothPlugin implements DuplexPlugin { private volatile boolean running = false; private volatile boolean wasEnabled = false, isEnabled = false; + private volatile BluetoothServerSocket socket = null; // Non-null if running has ever been true private volatile BluetoothAdapter adapter = null; @@ -149,7 +150,8 @@ class DroidtoothPlugin implements DuplexPlugin { tryToClose(ss); return; } - acceptContactConnections(ss); + socket = ss; + acceptContactConnections(); } private boolean enableBluetooth() { @@ -198,15 +200,15 @@ class DroidtoothPlugin implements DuplexPlugin { } } - private void acceptContactConnections(BluetoothServerSocket ss) { + private void acceptContactConnections() { while(true) { BluetoothSocket s; try { - s = ss.accept(); + s = socket.accept(); } catch(IOException e) { // This is expected when the socket is closed if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e); - tryToClose(ss); + tryToClose(socket); return; } callback.incomingConnectionCreated(wrapSocket(s)); @@ -220,6 +222,7 @@ class DroidtoothPlugin implements DuplexPlugin { public void stop() { running = false; + if(socket != null) tryToClose(socket); // Disable Bluetooth if we enabled it at startup if(isEnabled && !wasEnabled) disableBluetooth(); } @@ -246,6 +249,10 @@ class DroidtoothPlugin implements DuplexPlugin { } } + public boolean isRunning() { + return running && socket != null; + } + public boolean shouldPoll() { return true; } diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java index ed526aee2d..80ac29e959 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java @@ -72,7 +72,7 @@ class TorPlugin implements DuplexPlugin, EventHandler { private final File torDirectory, torFile, geoIpFile, configFile, doneFile; private final File cookieFile, pidFile, hostnameFile; - private volatile boolean running = false; + private volatile boolean running = false, networkEnabled = false; private volatile Process tor = null; private volatile int pid = -1; private volatile ServerSocket socket = null; @@ -509,6 +509,7 @@ class TorPlugin implements DuplexPlugin, EventHandler { if(!running) return; if(LOG.isLoggable(INFO)) LOG.info("Enabling network: " + enable); controlConnection.setConf("DisableNetwork", enable ? "0" : "1"); + networkEnabled = enable; } public void stop() throws IOException { @@ -534,6 +535,10 @@ class TorPlugin implements DuplexPlugin, EventHandler { } } + public boolean isRunning() { + return running && networkEnabled; + } + public boolean shouldPoll() { return true; } diff --git a/briar-api/src/org/briarproject/api/plugins/Plugin.java b/briar-api/src/org/briarproject/api/plugins/Plugin.java index 0eb66620ee..3389a73577 100644 --- a/briar-api/src/org/briarproject/api/plugins/Plugin.java +++ b/briar-api/src/org/briarproject/api/plugins/Plugin.java @@ -23,6 +23,9 @@ public interface Plugin { /** Stops the plugin. */ void stop() throws IOException; + /** Returns true if the plugin is running. */ + boolean isRunning(); + /** * Returns true if the plugin's {@link #poll(Collection)} method should be * called periodically to attempt to establish connections. diff --git a/briar-api/src/org/briarproject/api/plugins/PluginManager.java b/briar-api/src/org/briarproject/api/plugins/PluginManager.java index 330de8669b..efc336cf02 100644 --- a/briar-api/src/org/briarproject/api/plugins/PluginManager.java +++ b/briar-api/src/org/briarproject/api/plugins/PluginManager.java @@ -2,6 +2,7 @@ package org.briarproject.api.plugins; import java.util.Collection; +import org.briarproject.api.TransportId; import org.briarproject.api.lifecycle.Service; import org.briarproject.api.plugins.duplex.DuplexPlugin; @@ -11,6 +12,12 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin; */ public interface PluginManager extends Service { + /** + * Returns the plugin for the given transport, or null if no such plugin + * is running. + */ + Plugin getPlugin(TransportId t); + /** Returns any running duplex plugins that support invitations. */ Collection<DuplexPlugin> getInvitationPlugins(); } diff --git a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java b/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java index b78aba1bb2..6dee08bb2c 100644 --- a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java +++ b/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java @@ -9,6 +9,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; @@ -56,6 +57,7 @@ class PluginManagerImpl implements PluginManager { private final Poller poller; private final ConnectionDispatcher dispatcher; private final UiCallback uiCallback; + private final Map<TransportId, Plugin> plugins; private final List<SimplexPlugin> simplexPlugins; private final List<DuplexPlugin> duplexPlugins; @@ -73,6 +75,7 @@ class PluginManagerImpl implements PluginManager { this.poller = poller; this.dispatcher = dispatcher; this.uiCallback = uiCallback; + plugins = new ConcurrentHashMap<TransportId, Plugin>(); simplexPlugins = new CopyOnWriteArrayList<SimplexPlugin>(); duplexPlugins = new CopyOnWriteArrayList<DuplexPlugin>(); } @@ -104,10 +107,7 @@ class PluginManagerImpl implements PluginManager { } // Start the poller if(LOG.isLoggable(INFO)) LOG.info("Starting poller"); - List<Plugin> plugins = new ArrayList<Plugin>(); - plugins.addAll(simplexPlugins); - plugins.addAll(duplexPlugins); - poller.start(Collections.unmodifiableList(plugins)); + poller.start(plugins.values()); return true; } @@ -115,8 +115,7 @@ class PluginManagerImpl implements PluginManager { // Stop the poller if(LOG.isLoggable(INFO)) LOG.info("Stopping poller"); poller.stop(); - int plugins = simplexPlugins.size() + duplexPlugins.size(); - final CountDownLatch latch = new CountDownLatch(plugins); + final CountDownLatch latch = new CountDownLatch(plugins.size()); // Stop the simplex plugins if(LOG.isLoggable(INFO)) LOG.info("Stopping simplex plugins"); for(SimplexPlugin plugin : simplexPlugins) @@ -125,6 +124,7 @@ class PluginManagerImpl implements PluginManager { if(LOG.isLoggable(INFO)) LOG.info("Stopping duplex plugins"); for(DuplexPlugin plugin : duplexPlugins) pluginExecutor.execute(new PluginStopper(plugin, latch)); + plugins.clear(); simplexPlugins.clear(); duplexPlugins.clear(); // Wait for all the plugins to stop @@ -139,6 +139,10 @@ class PluginManagerImpl implements PluginManager { return true; } + public Plugin getPlugin(TransportId t) { + return plugins.get(t); + } + public Collection<DuplexPlugin> getInvitationPlugins() { List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>(); for(DuplexPlugin d : duplexPlugins) @@ -185,6 +189,7 @@ class PluginManagerImpl implements PluginManager { boolean started = plugin.start(); long duration = clock.currentTimeMillis() - start; if(started) { + plugins.put(id, plugin); simplexPlugins.add(plugin); if(LOG.isLoggable(INFO)) { String name = plugin.getClass().getSimpleName(); @@ -246,6 +251,7 @@ class PluginManagerImpl implements PluginManager { boolean started = plugin.start(); long duration = clock.currentTimeMillis() - start; if(started) { + plugins.put(id, plugin); duplexPlugins.add(plugin); if(LOG.isLoggable(INFO)) { String name = plugin.getClass().getSimpleName(); diff --git a/briar-core/src/org/briarproject/plugins/file/FilePlugin.java b/briar-core/src/org/briarproject/plugins/file/FilePlugin.java index 6b286559aa..77ed42e42c 100644 --- a/briar-core/src/org/briarproject/plugins/file/FilePlugin.java +++ b/briar-core/src/org/briarproject/plugins/file/FilePlugin.java @@ -55,6 +55,10 @@ public abstract class FilePlugin implements SimplexPlugin { return maxLatency; } + public boolean isRunning() { + return running; + } + public SimplexTransportReader createReader(ContactId c) { return null; } diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java index 4f483dc89e..13401c290c 100644 --- a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java +++ b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java @@ -146,6 +146,10 @@ abstract class TcpPlugin implements DuplexPlugin { if(socket != null) tryToClose(socket); } + public boolean isRunning() { + return running && socket != null && socket.isBound(); + } + public boolean shouldPoll() { return true; } diff --git a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java b/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java index 3bc65ce0f7..4572df83e1 100644 --- a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java +++ b/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java @@ -172,6 +172,10 @@ class BluetoothPlugin implements DuplexPlugin { tryToClose(socket); } + public boolean isRunning() { + return running; + } + public boolean shouldPoll() { return true; } diff --git a/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java b/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java index 58f1c421e3..4913cd82db 100644 --- a/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java +++ b/briar-desktop/src/org/briarproject/plugins/modem/ModemPlugin.java @@ -98,23 +98,8 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { } } - private boolean resetModem() { - if(!running) return false; - for(String portName : serialPortList.getPortNames()) { - if(LOG.isLoggable(INFO)) - LOG.info("Trying to initialise modem on " + portName); - modem = modemFactory.createModem(this, portName); - try { - if(!modem.start()) continue; - if(LOG.isLoggable(INFO)) - LOG.info("Initialised modem on " + portName); - return true; - } catch(IOException e) { - if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - } - } - running = false; - return false; + public boolean isRunning() { + return running; } public boolean shouldPoll() { @@ -180,6 +165,25 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { } } + private boolean resetModem() { + if(!running) return false; + for(String portName : serialPortList.getPortNames()) { + if(LOG.isLoggable(INFO)) + LOG.info("Trying to initialise modem on " + portName); + modem = modemFactory.createModem(this, portName); + try { + if(!modem.start()) continue; + if(LOG.isLoggable(INFO)) + LOG.info("Initialised modem on " + portName); + return true; + } catch(IOException e) { + if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } + } + running = false; + return false; + } + public DuplexTransportConnection createConnection(ContactId c) { if(!running) return null; // Get the ISO 3166 code for the caller's country -- GitLab