From cad1a105ca38e5247fc44e0789870ae45ba4f6e2 Mon Sep 17 00:00:00 2001 From: youtaol Date: Fri, 1 Jun 2012 14:35:03 +0800 Subject: [PATCH] Merge heads --- MyTracks/libs/README.txt | 3 + MyTracks/libs/antlib.jar | Bin 0 -> 31802 bytes .../res/values/arrays_do_not_translate.xml | 2 - MyTracks/res/values/do_not_translate.xml | 1 - MyTracks/res/values/keys.xml | 8 +- MyTracks/res/values/strings.xml | 66 +- MyTracks/res/xml/sensor_settings.xml | 16 +- MyTracks/src/com/dsi/ant/AntDefine.java | 268 ---- MyTracks/src/com/dsi/ant/AntInterface.java | 1310 ----------------- .../src/com/dsi/ant/AntInterfaceIntent.java | 37 - MyTracks/src/com/dsi/ant/AntMesg.java | 279 ---- MyTracks/src/com/dsi/ant/IAnt.aidl | 70 - MyTracks/src/com/dsi/ant/IAnt_6.aidl | 77 - .../src/com/dsi/ant/IServiceSettings.aidl | 29 - MyTracks/src/com/dsi/ant/Version.java | 35 - .../ant/exception/AntInterfaceException.java | 20 - .../dsi/ant/exception/AntRemoteException.java | 23 - .../AntServiceNotConnectedException.java | 19 - .../android/apps/mytracks/AntPreference.java | 64 - .../sensors/BluetoothSensorManager.java | 3 +- .../sensors/SensorManagerFactory.java | 7 +- .../sensors/ant/AntChannelIdMessage.java | 56 - .../ant/AntChannelResponseMessage.java | 49 - .../sensors/ant/AntDirectSensorManager.java | 242 --- .../services/sensors/ant/AntMessage.java | 32 - .../services/sensors/ant/AntSensor.java | 46 - .../services/sensors/ant/AntSensorBase.java | 73 - .../sensors/ant/AntSensorManager.java | 956 ++++++++---- .../ant/AntSrmBridgeSensorManager.java | 242 --- .../sensors/ant/AntStartupMessage.java | 35 - .../services/sensors/ant/AntUtils.java | 84 -- .../services/sensors/ant/CadenceSensor.java | 48 - .../sensors/ant/CadenceSpeedSensor.java | 48 - ...llector.java => ChannelConfiguration.java} | 26 +- .../services/sensors/ant/HeartRateSensor.java | 49 - .../sensors/ant/SensorEventCounter.java | 185 --- .../settings/SensorSettingsActivity.java | 55 +- .../apps/mytracks/AntPreferenceTest.java | 53 - .../sensors/ant/AntChannelIdMessageTest.java | 35 - .../ant/AntChannelResponseMessageTest.java | 36 - .../ant/AntDirectSensorManagerTest.java | 116 -- .../services/sensors/ant/AntMessageTest.java | 30 - .../sensors/ant/AntSensorManagerTest.java | 94 -- .../sensors/ant/AntStartupMessageTest.java | 29 - .../sensors/ant/SensorEventCounterTest.java | 35 - 45 files changed, 744 insertions(+), 4247 deletions(-) create mode 100644 MyTracks/libs/antlib.jar delete mode 100644 MyTracks/src/com/dsi/ant/AntDefine.java delete mode 100644 MyTracks/src/com/dsi/ant/AntInterface.java delete mode 100644 MyTracks/src/com/dsi/ant/AntInterfaceIntent.java delete mode 100644 MyTracks/src/com/dsi/ant/AntMesg.java delete mode 100644 MyTracks/src/com/dsi/ant/IAnt.aidl delete mode 100644 MyTracks/src/com/dsi/ant/IAnt_6.aidl delete mode 100644 MyTracks/src/com/dsi/ant/IServiceSettings.aidl delete mode 100644 MyTracks/src/com/dsi/ant/Version.java delete mode 100644 MyTracks/src/com/dsi/ant/exception/AntInterfaceException.java delete mode 100644 MyTracks/src/com/dsi/ant/exception/AntRemoteException.java delete mode 100644 MyTracks/src/com/dsi/ant/exception/AntServiceNotConnectedException.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/AntPreference.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelIdMessage.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelResponseMessage.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManager.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntMessage.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensor.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorBase.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSrmBridgeSensorManager.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntStartupMessage.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntUtils.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/CadenceSensor.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/CadenceSpeedSensor.java rename MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/{AntSensorDataCollector.java => ChannelConfiguration.java} (66%) delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/HeartRateSensor.java delete mode 100644 MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/SensorEventCounter.java delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/AntPreferenceTest.java delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelIdMessageTest.java delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelResponseMessageTest.java delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManagerTest.java delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntMessageTest.java delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorManagerTest.java delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntStartupMessageTest.java delete mode 100644 MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/SensorEventCounterTest.java diff --git a/MyTracks/libs/README.txt b/MyTracks/libs/README.txt index 033ec8f9e..3e7f84219 100644 --- a/MyTracks/libs/README.txt +++ b/MyTracks/libs/README.txt @@ -7,6 +7,9 @@ Android Support Package: android-support-v4-r7-googlemaps.jar - see https://github.com/petedoyle/android-support-v4-googlemaps +Ant+: +antlib.jar - see http://www.thisisant.com/pages/developer-zone/android-api + Google APIs Client Library for Java: commons-codec-1.3.jar commons-logging-1.1.1.jar diff --git a/MyTracks/libs/antlib.jar b/MyTracks/libs/antlib.jar new file mode 100644 index 0000000000000000000000000000000000000000..b4ff8fe047fb98fe4a7af3a64946862fabf81e61 GIT binary patch literal 31802 zcmaI71F+}7w=H~Z+n8h9w(*-|+qP}nwr$(CJ#%dPd~@Ib)>p6It9O&`>`p4(Np@#f zR;|6FC<6+H1_bqQwe%7a1p40=G$1e_IWc7+Iw^T^200;lDRD6+WqLXB?@1t_qrV_P ziZYN;)ggswVE_7n{Hu!p|47iGbb|leKtQu1P7z}Kk8H8+|MNLdCY)$Bm ztPPx;eALan@YK+IjkxF|vuLLhFV*RT+kpV26a}Qg+c_CJI;=b_xs5a-%o-C}qT;F1 zv|;iv@xi-Zusvz>Ai%In-FMMCQt~ak8KfDjsNQSDPPG#$+ z;SGPErj{`4YGvJ4*~|WJmag>JnbdSCS#t~r$mBrsELG*Se3bQ+$n5-;6S=ge=BS`r zLlU1s@|t;SsmfBcc2TW!3DZ}J57#C_4jhUnhM%&fT9Qu&?};}@qOuVA8Sx9{OwNqG zaN&_G?C3{0;T`+MoMB|VPVnAFTw07vWw@-jc zG3JTD@WFfYOjK6Q^^d?S39Jx3T)8N~PuL+Akv;z8C6U$F^1aRV$K|l1JkGY9{_E(G z_#ui{*OMZ8K9WXFr@WI8qb&^EDC>_-Du+FbdniuMl(dXd6q%17`eoP@G$QVUJzk1W zJg-mez;{ZkTn-S27tA>YII$dOJL_x-9X+boN^r-dcXouKPBXrohot^GATKVh8#3GDtU^Y$7WkM_`h3-4eLzY?m%B zw8i}MygS-{(s~VN@l8j8oKcv=J)=$6so9h(iDuIy$Bd`0Qs-h1R(20r89ln|R4v>R zA5+55^jKTGR91F_`G~vR-hg9ST3mar9uIYML?7tc?5h}`>=-P|t~{I@S$S~)-=7rB zAx^tsp>4n;6PD3TG=j(EsW;`%SzVQrO@@cGy=d9WN0g3OW-LuF@{9D*fKegv>|Z z3L~|o{u)Ua@_w#1;^J^I#(TM6=qzdCV%9NsQSC(UPnx)QRTAM7$ra}m_?g>f^G zShLxs-wf*MAAruVDB#t^vm(m?{E+||(D`bPaChL|dXb0kE8J6`VXG-9R!{FlaY#aG zKFdptN3zQ@&T4c*)Qt@D!*CC9x^ivOO)>7XhSaOXdTr!KbG!-PPS>t#%;yCX6KNl9 zq(?b4)VBr4t>s3%$KTfMcMV72auJ}HYv!ukq6o1TXwe7+>n_+l%2q6eh0zw?TP@P> zltpH%&L3!yi6R`L$-N6hpKNU$Bq0vrT;lmdT)M?@ z#@0rUG~&?NY#VIDt`6S@9@^01yqEC3C;_5hkb6znEmJZ(G38Con_^j97gISas%AzZ z_VU}kZ~c=hvXLyeUatsX*tL3F>es7klAd}K9U1(IBU0Y4zjgAEk`B2Wg7|~Zwj?e= zc54m{_Af?qVf^YsUx07SK0$E^fceWeaKZVD5196crhnQ)Df}teyunV(L+yb0OAn~_ zk8t>by%XOAMm_};hB!b3^oBTq^Gu)T>fPrW-RGFR81$cY$6px?pKVR=6q+7(2k)7N zZfS>3G(OuJANEEMJ90)I3`>7dTyxWyztWhzA)DMNnqC}DZ|F;ZV95PAlF}}D*;MV4 z{w^85H3zh%JYPK43Fot?r*R#NF)`E`>mFxdhN+ZHbdH*oJ*NBRz4i5fLQeaQe@aaI zO@Fqf|FA#&JHo*H^J4z0(qFfFYvr$3bpZCNyNZsFF^3Z6mocHYY>)ZMKiZdf0J;9A zy8cGrQ0s-yb5j}009t3^j{h1Ns)yJ;aPOotl-0ksp6a7GWC!G16uJlYX$s#5{#t|M zi+j7p_K9>mgyReL3Q)~+tN-j(8oB}Tl^u!$6(~4x1MQO-x&imi3*AHf1cvuRdKJO> zX1tYP{RHgCS-c+g=gr?z1PGKID1iEj59NV><6Yd$S-ryc>n-0V_3JI(rUmpB9@K&O z$qng2enVXB*;&47_3y3Ty7~829ozu>B%2^f8S zv0mKdHGO}BU)-3f`~4)&+|;Re_nE%=ramp%rT^?TzWS;~?DhY+f9=l+1TyCsdUNJ_ zX?~tnDF0!2b&`7{HA z2&0~gxSz3B3%=zTtJ1Xdyz?woHf^hpHK*(WMHuc5^h#3cBD156zly+qCk4qgeRVq1 z2AfT#jWSnNwcW?~wA(y`d;}|X0?G9So`O#S?XNB#c%&wq?2wL8`t&2h)HQQ(q-u;r zzr9Lma4%(G_(V9-EYftizxoE_+pIy+5u1C#!-nJXVyMAtyWD0G)=+!!1zZsYmyGDUBbSZ? zVimKkeqe!~6E`(h@^pv&-zKaO%0x-2bVIC*l$2B!3C+Lq>0Uh}~$oDELwE`CwQ)M&X*(+9KaZN65M zSmur_RTm92{kZzQW4U@*>uej`0EavC8CQdyg%U5@Q|Di-<6U;Q7dpc<8PehB-zUw8 zhGmf?20^7i)*lhtvedtuL4%xifTPAn#Q$AbQVk4n|D4nk2=o< z_}a~2_{0I1K$b+;y%vA_IfQiw*!^AHuafK*Z>EK1WAHn@0K+!Y4A!le=va#|!HDxY z87dWd5V99_7E$;+Lh7^d?&FB5bhDhls9t&6iyH0EnKGRI!jOT6BmF@x!%0k@vOFV% z6sXSBplNTdk|#m#GD|EY8KyX4lDQBVG&#uxgt-VQuN;ZZX>4hB-Go}RKY)J%{y#+u{r?mxN+yo37Dgtr z7EaD4wkD4Mi5r(#AxjV;Br!j^Ls`6-2;c$G_H=9OTL?oWFybiSmz>sQf>DA~TfS^q z#Qg%&9U()c-%;<1KT1D23}dMN(4N>R!UdT*>O6GCcZQaqgYK=k74FK7eC8uESG>5b z*aXmZDZG*ZnI`l+J#-occdKbOE~{v03SCr!$QN{jTPq*)GFw|+cCRY;S}XF$pVZhR zKVdiIMpsptlXa6*l+Ygo6y0k-m)vZ|MHIF z0NwTAzh}n;{-3-<@IQFxKi;U(fc92i>G+wwl(NMD0d5=+#Au`lR#BxO-j|d#LyA%Ycr8ZCPDgHLICw>V>@46!SS#%J)xDt!`Cq;P2Xew%N(8tI>4Z>Rf*I zo9$^bX=HpP>-&@2apJxA_S1Jo>vX(Ck@u@m+%+dhHu~7J`M}dovL@~8z%xzY@;NMJ z-~SSDX>5?}l+i6w`!ex8@c#Tgg{F|6(6QAL0kE~IE~CLy{tBwXHet8=R>X?*G~Nq8 z%x4u(tg7LuOiXYQky%m=Z_;I9L@L_IsfE9O?yXIoC2(_+$*U?Vs+(yk84=ouh5@QU zm_N^Npf3h{DJLkQFZOVy@lOC9@u|5kl~+4)6(LOn0J@>R0~^&=-n}jT6cMh?l+SH1 zYy+~ZI<|IpSJ(d7Zq1K9k^0*!61%SbF#(p&-piB%prtaKHPY{i>G zv%=8!AB6L*NRj3P4Mt$Q;3#}^x4ea99!!~>)>dO;S0@4sowwD;=fcNDN(kM#1}+U^2i<{TnW&|N<0(Ug@a}Qq6rQRMT%ejFCkezc zY`0j4rBXzjED-EgBw5p#-K*pay(c9pSlA?+(=nJDYmgVaogzfRmB+QFNT~~j{Vi3# zq_@WH`%o@ZKYU;~T8|Ta_#74g=8eeE+vkdou*S8i$|wtCyJ}WJ9u1RgWXoHb^GVqA z7ac}Q*|c>whFw@EmM2dN((x9D=DXeB)sOj~r}>Wb5}o>6Qi4J`}Sd^g3F|R3EeAzV;DBv@VPg z_4n8c>Nns0gb3CJd19-KWtgTk$vJrz9-PBj%?c`Rwe4X?rn^&IH7=1!R*Zj=7_6x6 zRl-XzOQaQw0__w={+Z19EJYa^zK$ra8^V;63$x5`Kuw;>2rkcoz*fno({MLdyjX1= z7XoNRk+gbg0_SH8a+Flp%+ zH}_Wto2+1J)_JbU>%J|WISNAnIlF>|=s~a9!B?V$Sb)jM3L=E+XEj2@>1=SzLo_&J zU;XXqiUYif)?za#ZWzrDOpg4mO+KaW#Nkiq*^S}%Ktk41Kd6;$%(car{aZ38=?w3K zK?OwtF+{&^8i%tx_m@2BP-PxDT=l*qDW+*jfKd}`=;rw?S!m+~1|b%%NI;Vh?-9Hg z=0gLfiutTQRwwL5ejmyZgx`0%Km-Hu{3AM~k#G zIoP6{YjNOkgJ$d-pyDFTHfql%$CNS|hQg zlLY+x&=Ijq>35-BCY;Qp%|*~t1b;fw`r1IxiY9wY6ZFF|$0JMe<*s+7+k)g-U|`nZ zXmru1LRj+SoSz>GW{J7}D1Q;qg^!S4K2m)T+$!cQ{dKEMni5SE6`#UX1?3;9fag@> z{&)#XiC-#vgS^0dq!YK=0gQC&i}na&N1h$gXsbH168y|eo$?QOe4n)sQk!{ef{ z@QE-Nj+WW!*QfSl#oqqAmjK{zrX+>{|83%ntt0JRNM?*EjJ`IX{`myh7OgKw%3_4~ zEEkvcFlDS%KdC~N$D8*kUHl*#hw_@jiV3VwkqF&VLNQ$f_t1bkFF&B(Nzsn&DsVT6 zc~jW75O_IT(wv^c3Yx;p6O;ivgk#%R;@OP5}Z^kH9Zs>(tH>_(k|80~~{Kz;Jhr zz(E-e|HHk=YHLn=GFHa@ue&xo2Q$Mb&shK8`^#r5F91CxIz!m8K4%vtboifk;-w%* zvbbCjwT9t)uG;bp_cNpx$z^Q(+N?Njq6QCZU(%4#nB|N3pp-)-GVWiTD*el>OnP!? zA$m>-Rzl!l#(p5bF7GuuhB2Tqs|r-pRn3=H9(JW8RPJ=EFL77&h1-Hw7&muAe4-R0 zWCd2J83)FVMJm3>-65-toGk`5mk8&a52eWQ1ws^XNL%ASM6;m+GZhdqdVrcQ2W%zu zz=87C=IKAfsRvV~suSo=Znj?!gjA94!O%zcuJ=xHp(CtUF{k*LlQGDg&$*8hTjx&+ zu+k;lIU6{nJn50_=G`D8;<@HqP_$-}`k=;YsA|>g0jLQliR;|0zL5tu_lyi)=qVFC z>hycR44$mTYwli+T{t@vj&v|3tw|&jjqvhNxjAH}XLw)(Jxeyq!5b1}=b0v2JJtp^ zvE|_}f32FBnvY>(KwAaLNjf|hPLs5TEaN~;pz%bv6aFbd*&6v^Ss?71 z&wTG+kFw!;kmh_tAPPEQ$jvMt)-o3OegH4~_12GuRjYv4%AEt>Fm)+w(yYHZfU-4% z6dw|l@VCTD5`kKmM7W(T*n`H6^n)trO{0IdIoxmfZ3i80@!Qhw zqvS*5h~zO1o~-)`X?E|%qofEtW&Z~^@kf@vv#IEdxxtg{_BobY57X@vjrd$Sr(r5z z`o~+d-aFcS;X7Is1=Kz$G=*%p5!5oBJ6hx;xld}uxsiTl`6xyaaDJN+ukWUQ?`Y~f zwV1w5CF5P+#Pc|SQFF^3E}Hh(?1$$ue=n za-2))^>UI~>>CzI@avlupqBI~s~5wBFB+J+cq2=v4f`5y$*Hz`_i$D`VsNgPwpBHi z{6boY3(?vV*UuE@W38I~#x^Z%bNspwmli~A0CW|R#!Sl*B}mQKw{}%rKG6I*V#8bs zwCsSeKFGXYFdlEhqCAZJoL>kRk{Ez~t*>xUFuucn&|juP#snGP!cmvTt*9R~y9Z}2 zOF+6vphD9eU}@(FmynpYOCHrvXgaNYYiSpLfgltX3RW)H->A+b?DFUR?u6ekdA>33 z-|&aee#lvMFwRXba?Ul#MPlhEPU&HHTL7b8zaj5!Ppj#R%08KlveVA1jywS=JzkwB zm(ByOM*Pym%JU;<5tSK-&V)YHa?_mRtlI$-E+LLO8iJTjTjF$78e&u$5?og^uJs`F zdWg(93?(Wp;i`3*fNJTyC3|)|2UzBXLk!jfH}suQ?M1p%q6Z4aRCYomc8Q=be=Nwj zGxes|pdxM|y@jG&hv`?hA%jLN;trq;kDLHk0z`$@fJ^mFr-r~e1I*vZTX4l!%A=i! zgN?lOv;kxh0`|S(IOBj$8j|e^Mv9LdbWQeYGmuW0#EY1m zLAJG*MpVUKiKc~yIe}9tW+_>z2fZp~*dAk#aexTkTh*TO8j;Zv#n?J8EB?T8ootKla zi_NUtq~GB_&XA7VMYLp@pKy+QU&&VnlBfXx${jn;T3-xPW7-xz3kXI^VuX< zri8GKc%(9Uj!G9*RcGtqaLS2gm~^7>fxG}lt+@$okZR5yiyffVWXRXmh@U(ggi$pJVQn;?qc>mTa|_j# zop1^{2??(;i&}PQ*?bY~vgF+vur5;=t1c`c zK1Hf2AT$N%-}y!dpytaT^1pk>eN>TWO@sFaa=6oeG@wfn}IH?ghfxeIaUMRHxqoMl5u!=ikA< zm?Kt2Msv#zgf)#GX`H;3TO6cYn8Zz9<&2#PvG{<*5tSOw0HVul`-NlWyUwJxYZ7>Tp$01E;rkNev;f2b3U-H5ayV&C#$d{Y{H{84tqM0Z5sUOgzKqkhQ)vtDP ziJy0_d_NMg$2yQNyMS-_d_UCFJ>d5j|L-7+g+4C$_qNk3(np40+;62mBgW7PX81*J z*3eW2s8j|~3FU)!Aka=Y8#CC+HnRmG$J&+5Cx93a1UilrSQN}tC2^_h@I-ZFxd`-y zWOajLFuR_()D+9;KlNf%&o~oz10BhA0;QV0(=GXGh@LVQxgK08S#w1&50;j!bvdox zUtF5K{Mn`6KF$aY&kmLirnaDQ2)FCfBgZz%rq|$UIm&jsY&O+jCYkCVk9hMxY+{eT z`G`PYQ1dt7?==43)cFFpFUMR)6-8#HXbXg3?>zqBy7_&Cr~jHmfYA2YBo9_V?-2gIB4Woc zK=*Nsk9ifdp9>u}aq8md@g>VdTBh+k%t?)OP8H+71xr#5shg(DxTgZ0g0o!^8nSaV zX|-?yJg6A+Bt}wK`nzH$=}we-N-Q?jbD895PZ~3%PWw#q?Qp_!3DK?#XnhsaCrn4= zVT`Pw(Y)Jr)JStNX_;T$`_24KwL;AUMiA+NH4UH_q^F=dXuXcy*~C2lt6-mmq(FDS zZs>~#tABT((1cT{CjV;461>Df>VhA(g>2vvy0k^=LL4RlYJmLlHGEkABsDC8X!whY zl(lcpF`8|P6VnhtK%ru^p%C546wd|DtPn80^rx9uf-Uu=V%3p6cKDt$;x7PY3Ld3J z3Xs;Mfw#RrXnc}?eva1+ozs*l(2H{ih}i$_o|uAPyz!|KFjT#(GSl^FYQuZQCxQJE#-xi^Fe&Sq8*y$MEV@fYYU|qIQTz z)R8I}6?ciT>;}1blXJNaYr>`#!nWf}uqDl$Je^UD^#m6l$i|{FVt}f3N%gw4MqA=i zXAE_9kFv>*luS(*IX_q<`ua(v2$2>x7g*!NJW7~gD@+X)LV&f)q|9gLa;p0UQ5+3$-KWvd?U5;9+Wt-Rm|c2Kh;&TNT_dnEKT^EtEiRyBgsX)HzO2c8sO zhmx%DCsX|%boD-AkJX@l56Bdan?mjj9|v_@_-Yd=brM(;R4e(b>o^Md?8}6tN$qSkOM`p$^taM%A(!7$ui5%uq*g1%$n}9PH zeNWu`m0v=Z^` zH5B35RB??~xXCt?gr!sw^j2O?!z>XQn>UB9=9UF#y(v$z1I^5OnW4svlw6mBS$&B~ z)g2EE)fSb69aWKy){*|sU>NJE-wo%r$xKf<@TD>R&cKW|z@@JGou`*fB}^GlxEI4Q zquc&%$Yfq(?q|9A5B|CFDQ z{tx8qe`RxQo&P(LlO(4wD2NogClnG{_(~V~8ZbH190AFYOI=+GttwJ=CvI6&3Lz6X z^18+Q3i=5crP}NSfHBPQcRlp7bg}q&`FViX$4Ns_2~XGvm~+JS9)lH>LKYwg>z=GS z^q3DPRw;CzSikeg(`-RGukY0u2vOl)Le{K zl(WsnWCmIc?h?ND!VGFVlgoaU+on^<^;qJXl?G}I+7c3u!GF2tPonsSgKe;|s}o&* z4hh0k@9aCTX9(Kshhb})WiH>Vt*^WKMex*vNzw(0lx4Z(?+vCB$VeuNAs2~ac4a&%fQ3PbiJ>c!<9EGodS3h=Y%*3Zw#k-;)rq z!L4LPZ>~(g*MrsgF1fTUIcCKSwiCo^PB5fsviDLit*r{C)0EMu%#2T~aStnABm$O3 z(2nh=I3)1qs*hnHaV_NvkzkKpV2)ueO4K#uX~o(dr5ZbgmMq8%O`z1zZJJbsU#M*aWjff7OaGJ^%|z6Gxp16BB1M9S(f+9tZwP z^&rOn8BKHBwSh_2RL#PHuN-+gT`5KgKe+Y8kd&P_0|e)E{$*Q{<*Owk|18tMd~N5m zT}dPfPNrnM7Cr<|s(&ruN`(b|N-+zTx_}+Dst8_Fk{Q=*?-Nj;1jO*ae`sPeM z!K*hFgZL+H=niSRaK3=W|3wae(Hq{e3595lj%9k0JEik2ryfGvZhT>ddp3{CJ^3lc zRFU=R#Fn5VL8^5r(c_kc#WFO5^)xd2YV(hcWLKN)UiEq`{zfJoi6+vL259Wgcul6W zbOHLh@4(c+HYK_S{Jmp%^nRO>k)3IZC`mIgibk$h(?y1}#6d8~Hvd#{v_Q-~y)Xaq zOyv^%iqh3()^&7?84nK?v{BNc2=|a;mSfBt!ny1{SB5x&s?2WKVliLTaXAUT$TkIw zkDro7)-%3LLMuN)M50}?b~Nh7-BjHcmfGNA21+h0hby;=FlVcY^xJ!buUe|hDLPc> zLm^UYvz01dr{a!E?_WUFWaIRbVxt5=*>OM=Rz)5c|2L!FmK6{ zwLfu6%;wyt^W&mxIOpNZjM#Xr33qqRl<2NDU~aUwv^oEKobemr@Z)}n$t3vzW z8J8H2JT4d$3B~r*-E0a14B?5QBlv&MoV3ua$DOP0%5KbQQ{5OU4!@G?bRrFw8soV=ycYQYXwk!Ku2BW5 z7~GZ30a_ZT1&a+WCh%x3rm&Lq)Har#z1<^+52=x=Q;qUdbdzqni|!?@T7^7!^YYV=M|@NtM=_ZO0gY$V_-r>^#!Rg)E(4 za4JRIF=8S zMk&V3?tEMZ01`(uL&8>;W@Qp|ia)0+egMA_*4bC%v7J7*W)}Pw35t2ITF27SP1K;P zv%B=Bfsm%IF|&AZ`3XG*dC?_8`KvsFi{(+Hon7nC^;bk{%dEl8_F=V37s~`qI87A4 zD>cXZNygWJQxD~ zOMl#Go%*qLNINq;f00q-_6c_+-eGqv-a&WBSJu(8pgADI^Xlk>>J3usn?DD6GmV9SC8mC zL|@<|%s{>2SKiyVXgxSz=%chiz0udd`>FUU5d(0_%*t`CcJLIRf>jUS0OrSbRZWW1{!Kd|8g#{P!kbZT8z( zd?8D z!qwhvM+w3GWV;gyG3)jzg1;%S{b0P~;`eBdyA*D}0tM(Qr$L3kv6+6%Lj3YjKRpKY zkUqtje$ue~us_j>f2fb@0{ZAb-$LtuO5^=xs();Ve`3{dx&r$sUOxi;h>kxB;(sKS z&j?|^BW`cX0{zGz{pgQ>Lgs%;;(w%X>q7eakncWf(r?^^e_nq5d=tIK8TJZ9ynSo8 zBc6^N&cf&U4UI#;vfg%_rt_@q*~ut>N96InDxVL$>hYZGz1DE3{Qgn>0o?UfeP@~T zzY6@9ngCviSik(ADhcfKSgRv^VZb z4&?36G_HlQ7XKlMxKwr&(&g(f$XFwa(bPEg^@boDl*3|DBMWPqR5F%Cl&sXMzvf*f zTCo_yZkXl)%^}x|LH4Q5UCwQS0gH3Oi1}NCzA(*#TGB6|&GBD797PRiTMk!~Vv^rh zrn^}$y$^XDcH$m~LtzADh47E)DaH}fp9u@+f~@K_Ax0~`rS{f-Gnu>U-ug50B+UE; ziN655LRays_=|%gD?6Z&E`G9PWuk9Nu+qh`&!
GS}DG7JQ)1pRz&l$vLcpaXx~ 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 literal 0 HcmV?d00001 diff --git a/MyTracks/res/values/arrays_do_not_translate.xml b/MyTracks/res/values/arrays_do_not_translate.xml index 4ca399897..f2fc910ab 100644 --- a/MyTracks/res/values/arrays_do_not_translate.xml +++ b/MyTracks/res/values/arrays_do_not_translate.xml @@ -161,14 +161,12 @@ limitations under the License. @string/settings_sensor_type_none @string/settings_sensor_type_ant - @string/settings_sensor_type_srm @string/settings_sensor_type_polar @string/settings_sensor_type_zephyr @string/sensor_type_value_none @string/sensor_type_value_ant - @string/sensor_type_value_srm_ant_bridge @string/sensor_type_value_polar @string/sensor_type_value_zephyr diff --git a/MyTracks/res/values/do_not_translate.xml b/MyTracks/res/values/do_not_translate.xml index 3bad2cdf7..06045fb5c 100644 --- a/MyTracks/res/values/do_not_translate.xml +++ b/MyTracks/res/values/do_not_translate.xml @@ -30,7 +30,6 @@ limitations under the License. ANT NONE POLAR - SRM_ANT_BRIDGE ZEPHYR DYNAMIC FIXED diff --git a/MyTracks/res/values/keys.xml b/MyTracks/res/values/keys.xml index 64e356e48..f7fa8a154 100644 --- a/MyTracks/res/values/keys.xml +++ b/MyTracks/res/values/keys.xml @@ -18,10 +18,8 @@ limitations under the License. allowAccess announcementFrequency - antCadenceSensorId - antCadenceSpeedSensorId - antHeartRateSensorId - antSrmBridgeSensorId + antHeartRateMonitorId + antSpeedDistanceMonitorId autoResumeTrackCurrentRetry autoResumeTrackTimeout bluetoothSensor @@ -72,6 +70,8 @@ limitations under the License. settingsReset settingsSensor settingsSensorAnt + settingsSensorAntResetHeartRateMonitor + settingsSensorAntResetSpeedDistanceMonitor settingsSensorBluetooth settingsSensorBluetoothPairing settingsSensorRoot diff --git a/MyTracks/res/values/strings.xml b/MyTracks/res/values/strings.xml index c8e70d00c..dbc46784a 100644 --- a/MyTracks/res/values/strings.xml +++ b/MyTracks/res/values/strings.xml @@ -1726,11 +1726,6 @@ limitations under the License. Character limit: ~26 (1 line)"> Sensor - - Not paired. - + %1$d: device id number. E.g., '1'."> Paired with: %1$d. - - Connected to %1$s + + Reset heart rate monitor + + + Reset speed distance monitor The Bluetooth sensor to connect to. + + Connected to %1$s + + + Not connected. + - ANT+ heart rate + ANT+ Polar Bluetooth - - SRM ANT+ bridge - @@ -1833,21 +1838,6 @@ limitations under the License. Character limit: ~21 (1 line)"> Zephyr Bluetooth - - Unpair ANT+ heart rate - - - Unpair SRM ANT+ bridge - - - + + \ No newline at end of file diff --git a/MyTracks/src/com/dsi/ant/AntDefine.java b/MyTracks/src/com/dsi/ant/AntDefine.java deleted file mode 100644 index bda615df9..000000000 --- a/MyTracks/src/com/dsi/ant/AntDefine.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright 2010 Dynastream Innovations Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.dsi.ant; - - - -/** - * The Android Ant API is not finalized, and *will* change. Use at your - * own risk. - * - * Public API for controlling the Ant Service. - * AntDefines contains definitions commonly used in ANT messaging. - * - * @hide - */ -public class AntDefine { - - ////////////////////////////////////////////// - // Valid Configuration Values - ////////////////////////////////////////////// - public static final byte MIN_BIN = 0; - public static final byte MAX_BIN = 10; - - public static final short MIN_DEVICE_ID = 0; - public static final short MAX_DEVICE_ID = (short)65535; - - public static final short MIN_BUFFER_THRESHOLD = 0; - public static final short MAX_BUFFER_THRESHOLD = 996; - - ////////////////////////////////////////////// - // ANT Message Payload Size - ////////////////////////////////////////////// - public static final byte ANT_STANDARD_DATA_PAYLOAD_SIZE =((byte)8); - - ////////////////////////////////////////////// - // ANT LIBRARY Extended Data Message Fields - // NOTE: You must check the extended message - // bitfield first to find out which fields - // are present before accessing them! - ////////////////////////////////////////////// - public static final byte ANT_EXT_MESG_DEVICE_ID_FIELD_SIZE =((byte)4); - //public static final byte ANT_EXT_STRING_SIZE =((byte)19); // this is the additional buffer space required required for setting USB Descriptor strings - public static final byte ANT_EXT_STRING_SIZE =((byte)0); // changed to 0 as we will not be dealing with ANT USB parts. - - ////////////////////////////////////////////// - // ANT Extended Data Message Bifield Definitions - ////////////////////////////////////////////// - public static final byte ANT_EXT_MESG_BITFIELD_DEVICE_ID =((byte)0x80); // first field after bitfield - public static final byte ANT_EXT_MESG_BITFIELD_RSSI =((byte)0x40); // next field after ID, if there is one - public static final byte ANT_EXT_MESG_BITFIELD_TIME_STAMP =((byte)0x20); // next field after RSSI, if there is one - - // 4 bits free reserved set to 0 - public static final byte ANT_EXT_MESG_BIFIELD_EXTENSION =((byte)0x01); - - // extended message input bitfield defines - public static final byte ANT_EXT_MESG_BITFIELD_OVERWRITE_SHARED_ADR =((byte)0x10); - public static final byte ANT_EXT_MESG_BITFIELD_TRANSMISSION_TYPE =((byte)0x08); - - ////////////////////////////////////////////// - // ID Definitions - ////////////////////////////////////////////// - public static final byte ANT_ID_SIZE =((byte)4); - public static final byte ANT_ID_TRANS_TYPE_OFFSET =((byte)3); - public static final byte ANT_ID_DEVICE_TYPE_OFFSET =((byte)2); - public static final byte ANT_ID_DEVICE_NUMBER_HIGH_OFFSET =((byte)1); - public static final byte ANT_ID_DEVICE_NUMBER_LOW_OFFSET =((byte)0); - public static final byte ANT_ID_DEVICE_TYPE_PAIRING_FLAG =((byte)0x80); - - public static final byte ANT_TRANS_TYPE_SHARED_ADDR_MASK =((byte)0x03); - public static final byte ANT_TRANS_TYPE_1_BYTE_SHARED_ADDRESS =((byte)0x02); - public static final byte ANT_TRANS_TYPE_2_BYTE_SHARED_ADDRESS =((byte)0x03); - - ////////////////////////////////////////////// - // Assign Channel Parameters - ////////////////////////////////////////////// - public static final byte PARAMETER_RX_NOT_TX =((byte)0x00); - public static final byte PARAMETER_TX_NOT_RX =((byte)0x10); - public static final byte PARAMETER_SHARED_CHANNEL =((byte)0x20); - public static final byte PARAMETER_NO_TX_GUARD_BAND =((byte)0x40); - public static final byte PARAMETER_ALWAYS_RX_WILD_CARD_SEARCH_ID =((byte)0x40); //Pre-AP2 - public static final byte PARAMETER_RX_ONLY =((byte)0x40); - - ////////////////////////////////////////////// - // Ext. Assign Channel Parameters - ////////////////////////////////////////////// - public static final byte EXT_PARAM_ALWAYS_SEARCH =((byte)0x01); - public static final byte EXT_PARAM_FREQUENCY_AGILITY =((byte)0x04); - - ////////////////////////////////////////////// - // Radio TX Power Definitions - ////////////////////////////////////////////// - public static final byte RADIO_TX_POWER_LVL_MASK =((byte)0x03); - - public static final byte RADIO_TX_POWER_LVL_0 =((byte)0x00); //(formerly: RADIO_TX_POWER_MINUS20DB); lowest - public static final byte RADIO_TX_POWER_LVL_1 =((byte)0x01); //(formerly: RADIO_TX_POWER_MINUS10DB); - public static final byte RADIO_TX_POWER_LVL_2 =((byte)0x02); //(formerly: RADIO_TX_POWER_MINUS5DB); - public static final byte RADIO_TX_POWER_LVL_3 =((byte)0x03); //(formerly: RADIO_TX_POWER_0DB); highest - - ////////////////////////////////////////////// - // Channel Status - ////////////////////////////////////////////// - public static final byte STATUS_CHANNEL_STATE_MASK =((byte)0x03); - public static final byte STATUS_UNASSIGNED_CHANNEL =((byte)0x00); - public static final byte STATUS_ASSIGNED_CHANNEL =((byte)0x01); - public static final byte STATUS_SEARCHING_CHANNEL =((byte)0x02); - public static final byte STATUS_TRACKING_CHANNEL =((byte)0x03); - - ////////////////////////////////////////////// - // Standard capabilities defines - ////////////////////////////////////////////// - public static final byte CAPABILITIES_NO_RX_CHANNELS =((byte)0x01); - public static final byte CAPABILITIES_NO_TX_CHANNELS =((byte)0x02); - public static final byte CAPABILITIES_NO_RX_MESSAGES =((byte)0x04); - public static final byte CAPABILITIES_NO_TX_MESSAGES =((byte)0x08); - public static final byte CAPABILITIES_NO_ACKD_MESSAGES =((byte)0x10); - public static final byte CAPABILITIES_NO_BURST_TRANSFER =((byte)0x20); - - ////////////////////////////////////////////// - // Advanced capabilities defines - ////////////////////////////////////////////// - public static final byte CAPABILITIES_OVERUN_UNDERRUN =((byte)0x01); // Support for this functionality has been dropped - public static final byte CAPABILITIES_NETWORK_ENABLED =((byte)0x02); - public static final byte CAPABILITIES_AP1_VERSION_2 =((byte)0x04); // This Version of the AP1 does not support transmit and only had a limited release - public static final byte CAPABILITIES_SERIAL_NUMBER_ENABLED =((byte)0x08); - public static final byte CAPABILITIES_PER_CHANNEL_TX_POWER_ENABLED =((byte)0x10); - public static final byte CAPABILITIES_LOW_PRIORITY_SEARCH_ENABLED =((byte)0x20); - public static final byte CAPABILITIES_SCRIPT_ENABLED =((byte)0x40); - public static final byte CAPABILITIES_SEARCH_LIST_ENABLED =((byte)0x80); - - ////////////////////////////////////////////// - // Advanced capabilities 2 defines - ////////////////////////////////////////////// - public static final byte CAPABILITIES_LED_ENABLED =((byte)0x01); - public static final byte CAPABILITIES_EXT_MESSAGE_ENABLED =((byte)0x02); - public static final byte CAPABILITIES_SCAN_MODE_ENABLED =((byte)0x04); - public static final byte CAPABILITIES_RESERVED =((byte)0x08); - public static final byte CAPABILITIES_PROX_SEARCH_ENABLED =((byte)0x10); - public static final byte CAPABILITIES_EXT_ASSIGN_ENABLED =((byte)0x20); - public static final byte CAPABILITIES_FREE_1 =((byte)0x40); - public static final byte CAPABILITIES_FIT1_ENABLED =((byte)0x80); - - ////////////////////////////////////////////// - // Advanced capabilities 3 defines - ////////////////////////////////////////////// - public static final byte CAPABILITIES_SENSRCORE_ENABLED =((byte)0x01); - public static final byte CAPABILITIES_RESERVED_1 =((byte)0x02); - public static final byte CAPABILITIES_RESERVED_2 =((byte)0x04); - public static final byte CAPABILITIES_RESERVED_3 =((byte)0x08); - - - ////////////////////////////////////////////// - // Burst Message Sequence - ////////////////////////////////////////////// - public static final byte CHANNEL_NUMBER_MASK =((byte)0x1F); - public static final byte SEQUENCE_NUMBER_MASK =((byte)0xE0); - public static final byte SEQUENCE_NUMBER_ROLLOVER =((byte)0x60); - public static final byte SEQUENCE_FIRST_MESSAGE =((byte)0x00); - public static final byte SEQUENCE_LAST_MESSAGE =((byte)0x80); - public static final byte SEQUENCE_NUMBER_INC =((byte)0x20); - - ////////////////////////////////////////////// - // Control Message Flags - ////////////////////////////////////////////// - public static final byte BROADCAST_CONTROL_BYTE =((byte)0x00); - public static final byte ACKNOWLEDGED_CONTROL_BYTE =((byte)0xA0); - - ////////////////////////////////////////////// - // Response / Event Codes - ////////////////////////////////////////////// - public static final byte RESPONSE_NO_ERROR =((byte)0x00); - public static final byte NO_EVENT =((byte)0x00); - - public static final byte EVENT_RX_SEARCH_TIMEOUT =((byte)0x01); - public static final byte EVENT_RX_FAIL =((byte)0x02); - public static final byte EVENT_TX =((byte)0x03); - public static final byte EVENT_TRANSFER_RX_FAILED =((byte)0x04); - public static final byte EVENT_TRANSFER_TX_COMPLETED =((byte)0x05); - public static final byte EVENT_TRANSFER_TX_FAILED =((byte)0x06); - public static final byte EVENT_CHANNEL_CLOSED =((byte)0x07); - public static final byte EVENT_RX_FAIL_GO_TO_SEARCH =((byte)0x08); - public static final byte EVENT_CHANNEL_COLLISION =((byte)0x09); - public static final byte EVENT_TRANSFER_TX_START =((byte)0x0A); // a pending transmit transfer has begun - - public static final byte EVENT_CHANNEL_ACTIVE =((byte)0x0F); - - public static final byte EVENT_TRANSFER_TX_NEXT_MESSAGE =((byte)0x11); // only enabled in FIT1 - - public static final byte CHANNEL_IN_WRONG_STATE =((byte)0x15); // returned on attempt to perform an action from the wrong channel state - public static final byte CHANNEL_NOT_OPENED =((byte)0x16); // returned on attempt to communicate on a channel that is not open - public static final byte CHANNEL_ID_NOT_SET =((byte)0x18); // returned on attempt to open a channel without setting the channel ID - public static final byte CLOSE_ALL_CHANNELS =((byte)0x19); // returned when attempting to start scanning mode, when channels are still open - - public static final byte TRANSFER_IN_PROGRESS =((byte)0x1F); // returned on attempt to communicate on a channel with a TX transfer in progress - public static final byte TRANSFER_SEQUENCE_NUMBER_ERROR =((byte)0x20); // returned when sequence number is out of order on a Burst transfer - public static final byte TRANSFER_IN_ERROR =((byte)0x21); - public static final byte TRANSFER_BUSY =((byte)0x22); - - public static final byte INVALID_MESSAGE_CRC =((byte)0x26); // returned if there is a framing error on an incomming message - public static final byte MESSAGE_SIZE_EXCEEDS_LIMIT =((byte)0x27); // returned if a data message is provided that is too large - public static final byte INVALID_MESSAGE =((byte)0x28); // returned when the message has an invalid parameter - public static final byte INVALID_NETWORK_NUMBER =((byte)0x29); // returned when an invalid network number is provided - public static final byte INVALID_LIST_ID =((byte)0x30); // returned when the provided list ID or size exceeds the limit - public static final byte INVALID_SCAN_TX_CHANNEL =((byte)0x31); // returned when attempting to transmit on channel 0 when in scan mode - - public static final byte INVALID_PARAMETER_PROVIDED =((byte)0x33); // returned when an invalid parameter is specified in a configuration message - - public static final byte EVENT_SERIAL_QUE_OVERFLOW =((byte)0x34); - public static final byte EVENT_QUE_OVERFLOW =((byte)0x35); // ANT event que has overflowed and lost 1 or more events - - public static final byte EVENT_CLK_ERROR =((byte)0x36); // debug event for XOSC16M on LE1 - - public static final byte SCRIPT_FULL_ERROR =((byte)0x40); // error writing to script, memory is full - public static final byte SCRIPT_WRITE_ERROR =((byte)0x41); // error writing to script, bytes not written correctly - public static final byte SCRIPT_INVALID_PAGE_ERROR =((byte)0x42); // error accessing script page - public static final byte SCRIPT_LOCKED_ERROR =((byte)0x43); // the scripts are locked and can't be dumped - - public static final byte NO_RESPONSE_MESSAGE =((byte)0x50); // returned to the Command_SerialMessageProcess function, so no reply message is generated - public static final byte RETURN_TO_MFG =((byte)0x51); // default return to any mesg when the module determines that the mfg procedure has not been fully completed - - public static final byte FIT_ACTIVE_SEARCH_TIMEOUT =((byte)0x60); // Fit1 only event added for timeout of the pairing state after the Fit module becomes active - public static final byte FIT_WATCH_PAIR =((byte)0x61); // Fit1 only - public static final byte FIT_WATCH_UNPAIR =((byte)0x62); // Fit1 only - - public static final byte USB_STRING_WRITE_FAIL =((byte)0x70); - - // Internal only events below this point - public static final byte INTERNAL_ONLY_EVENTS =((byte)0x80); - public static final byte EVENT_RX =((byte)0x80); // INTERNAL: Event for a receive message - public static final byte EVENT_NEW_CHANNEL =((byte)0x81); // INTERNAL: EVENT for a new active channel - public static final byte EVENT_PASS_THRU =((byte)0x82); // INTERNAL: Event to allow an upper stack events to pass through lower stacks - - public static final byte EVENT_BLOCKED =((byte)0xFF); // INTERNAL: Event to replace any event we do not wish to go out, will also zero the size of the Tx message - - /////////////////////////////////////////////////////// - // Script Command Codes - /////////////////////////////////////////////////////// - public static final byte SCRIPT_CMD_FORMAT =((byte)0x00); - public static final byte SCRIPT_CMD_DUMP =((byte)0x01); - public static final byte SCRIPT_CMD_SET_DEFAULT_SECTOR =((byte)0x02); - public static final byte SCRIPT_CMD_END_SECTOR =((byte)0x03); - public static final byte SCRIPT_CMD_END_DUMP =((byte)0x04); - public static final byte SCRIPT_CMD_LOCK =((byte)0x05); - - /////////////////////////////////////////////////////// - // Reset Mesg Codes - /////////////////////////////////////////////////////// - public static final byte RESET_FLAGS_MASK =((byte)0xE0); - public static final byte RESET_SUSPEND =((byte)0x80); // this must follow bitfield def - public static final byte RESET_SYNC =((byte)0x40); // this must follow bitfield def - public static final byte RESET_CMD =((byte)0x20); // this must follow bitfield def - public static final byte RESET_WDT =((byte)0x02); - public static final byte RESET_RST =((byte)0x01); - public static final byte RESET_POR =((byte)0x00); - -} \ No newline at end of file diff --git a/MyTracks/src/com/dsi/ant/AntInterface.java b/MyTracks/src/com/dsi/ant/AntInterface.java deleted file mode 100644 index e8c6a0b67..000000000 --- a/MyTracks/src/com/dsi/ant/AntInterface.java +++ /dev/null @@ -1,1310 +0,0 @@ -/* - * Copyright 2010 Dynastream Innovations Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.dsi.ant; - -import com.dsi.ant.exception.AntInterfaceException; -import com.dsi.ant.exception.AntRemoteException; -import com.dsi.ant.exception.AntServiceNotConnectedException; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.net.Uri; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import java.util.Arrays; - -/** - * Public API for controlling the Ant Service. AntInterface is a proxy - * object for controlling the Ant Service via IPC. Creating a AntInterface - * object will create a binding with the Ant service. - * - * @hide - */ -public class AntInterface { - - /** The Log Tag. */ - public static final String TAG = "ANTInterface"; - - /** Enable debug logging. */ - public static boolean DEBUG = false; - - /** Search string to find ANT Radio Proxy Service in the Android Marketplace */ - private static final String MARKET_SEARCH_TEXT_DEFAULT = "ANT Radio Service Dynastream Innovations Inc"; - - /** Name of the ANT Radio shared library */ - private static final String ANT_LIBRARY_NAME = "com.dsi.ant.antradio_library"; - - /** Inter-process communication with the ANT Radio Proxy Service. */ - private static IAnt_6 sAntReceiver = null; - - /** Singleton instance of this class. */ - private static AntInterface INSTANCE; - - /** Used when obtaining a reference to the singleton instance. */ - private static Object INSTANCE_LOCK = new Object(); - - /** The context to use. */ - private Context sContext = null; - - /** Listens to changes to service connection status. */ - private ServiceListener sServiceListener; - - /** Is the ANT Radio Proxy Service connected. */ - private static boolean sServiceConnected = false; - - /** The version code (eg. 1) of ANTLib used by the ANT application service */ - private static int mServiceLibraryVersionCode = 0; - - /** Has support for ANT already been checked */ - private static boolean mCheckedAntSupported = false; - - /** Is ANT supported on this device */ - private static boolean mAntSupported = false; - - /** - * An interface for notifying AntInterface IPC clients when they have been - * connected to the ANT service. - */ - public interface ServiceListener - { - /** - * Called to notify the client when this proxy object has been - * connected to the ANT service. Clients must wait for - * this callback before making IPC calls on the ANT - * service. - */ - public void onServiceConnected(); - - /** - * Called to notify the client that this proxy object has been - * disconnected from the ANT service. Clients must not - * make IPC calls on the ANT service after this callback. - * This callback will currently only occur if the application hosting - * the BluetoothAg service, but may be called more often in future. - */ - public void onServiceDisconnected(); - } - - - //Constructor - /** - * Instantiates a new ant interface. - * - * @param context the context - * @param listener the listener - * @since 1.0 - */ - private AntInterface(Context context, ServiceListener listener) - { - // This will be around as long as this process is - sContext = context; - sServiceListener = listener; - } - - /** - * Gets the single instance of AntInterface, creating it if it doesn't exist. - * Only the initial request for an instance will have context and listener set to the requested objects. - * - * @param context the context used to bind to the remote service. - * @param listener the listener to be notified of status changes. - * @return the AntInterface instance. - * @since 1.0 - */ - public static AntInterface getInstance(Context context,ServiceListener listener) - { - if(DEBUG) Log.d(TAG, "getInstance"); - - synchronized (INSTANCE_LOCK) - { - if(!hasAntSupport(context)) - { - if(DEBUG) Log.d(TAG, "getInstance: ANT not supported"); - - return null; - } - - if (INSTANCE == null) - { - if(DEBUG) Log.d(TAG, "getInstance: Creating new instance"); - - INSTANCE = new AntInterface(context,listener); - } - else - { - if(DEBUG) Log.d(TAG, "getInstance: Using existing instance"); - } - - if(!sServiceConnected) - { - if(DEBUG) Log.d(TAG, "getInstance: No connection to proxy service, attempting connection"); - - if(!INSTANCE.initService()) - { - Log.e(TAG, "getInstance: No connection to proxy service"); - - INSTANCE.destroy(); - INSTANCE = null; - } - } - - return INSTANCE; - } - } - - /** - * Go to market. - * - * @param pContext the context - * @param pSearchText the search text - * @since 1.2 - */ - public static void goToMarket(Context pContext, String pSearchText) - { - if(null == pSearchText) - { - goToMarket(pContext); - } - else - { - if(DEBUG) Log.i(TAG, "goToMarket: Search text = "+ pSearchText); - - Intent goToMarket = null; - goToMarket = new Intent(Intent.ACTION_VIEW,Uri.parse("http://market.android.com/search?q=" + pSearchText)); - goToMarket.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - pContext.startActivity(goToMarket); - } - } - - /** - * Go to market. - * - * @param pContext the context - * @since 1.2 - */ - public static void goToMarket(Context pContext) - { - if(DEBUG) Log.d(TAG, "goToMarket"); - - goToMarket(pContext, MARKET_SEARCH_TEXT_DEFAULT); - } - - /** - * Class for interacting with the ANT interface. - */ - private final ServiceConnection sIAntConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName pClassName, IBinder pService) { - // This is called when the connection with the service has been - // established, giving us the service object we can use to - // interact with the service. We are communicating with our - // service through an IDL interface, so get a client-side - // representation of that from the raw service object. - if(DEBUG) Log.d(TAG, "sIAntConnection onServiceConnected()"); - sAntReceiver = IAnt_6.Stub.asInterface(pService); - - sServiceConnected = true; - - // Notify the attached application if it is registered - if (sServiceListener != null) - { - sServiceListener.onServiceConnected(); - } - else - { - if(DEBUG) Log.d(TAG, "sIAntConnection onServiceConnected: No service listener registered"); - } - } - - public void onServiceDisconnected(ComponentName pClassName) { - // This is called when the connection with the service has been - // unexpectedly disconnected -- that is, its process crashed. - if(DEBUG) Log.d(TAG, "sIAntConnection onServiceDisconnected()"); - sAntReceiver = null; - - sServiceConnected = false; - mServiceLibraryVersionCode = 0; - - // Notify the attached application if it is registered - if (sServiceListener != null) - { - sServiceListener.onServiceDisconnected(); - } - else - { - if(DEBUG) Log.d(TAG, "sIAntConnection onServiceDisconnected: No service listener registered"); - } - - // Try and rebind to the service - INSTANCE.releaseService(); - INSTANCE.initService(); - } - }; - - /** - * Binds this activity to the ANT service. - * - * @return true, if successful - */ - private boolean initService() { - if(DEBUG) Log.d(TAG, "initService() entered"); - - boolean ret = false; - - if(!sServiceConnected) - { - ret = sContext.bindService(new Intent(IAnt_6.class.getName()), sIAntConnection, Context.BIND_AUTO_CREATE); - if(DEBUG) Log.i(TAG, "initService(): Bound with ANT service: " + ret); - } - else - { - if(DEBUG) Log.d(TAG, "initService: already initialised service"); - ret = true; - } - - return ret; - } - - /** Unbinds this activity from the ANT service. */ - private void releaseService() { - if(DEBUG) Log.d(TAG, "releaseService() entered"); - - // TODO Make sure can handle multiple calls to onDestroy - if(sServiceConnected) - { - sContext.unbindService(sIAntConnection); - sServiceConnected = false; - } - - if(DEBUG) Log.d(TAG, "releaseService() unbound."); - } - - /** - * True if this activity can communicate with the ANT service. - * - * @return true, if service is connected - * @since 1.2 - */ - public boolean isServiceConnected() - { - return sServiceConnected; - } - - /** - * Destroy. - * - * @return true, if successful - * @since 1.0 - */ - public boolean destroy() - { - if(DEBUG) Log.d(TAG, "destroy"); - - releaseService(); - - INSTANCE = null; - - return true; - } - - - ////------------------------------------------------- - - /** - * Enable. - * - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void enable() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.enable()) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Disable. - * - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void disable() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.disable()) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Checks if is enabled. - * - * @return true, if is enabled. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public boolean isEnabled() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.isEnabled(); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT tx message. - * - * @param message the message - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTTxMessage(byte[] message) throws AntInterfaceException - { - if(DEBUG) Log.d(TAG, "ANTTxMessage"); - - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTTxMessage(message)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT reset system. - * - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTResetSystem() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTResetSystem()) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT unassign channel. - * - * @param channelNumber the channel number - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTUnassignChannel(byte channelNumber) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTUnassignChannel(channelNumber)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT assign channel. - * - * @param channelNumber the channel number - * @param channelType the channel type - * @param networkNumber the network number - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTAssignChannel(byte channelNumber, byte channelType, byte networkNumber) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTAssignChannel(channelNumber, channelType, networkNumber)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT set channel id. - * - * @param channelNumber the channel number - * @param deviceNumber the device number - * @param deviceType the device type - * @param txType the tx type - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSetChannelId(byte channelNumber, short deviceNumber, byte deviceType, byte txType) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSetChannelId(channelNumber, deviceNumber, deviceType, txType)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT set channel period. - * - * @param channelNumber the channel number - * @param channelPeriod the channel period - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSetChannelPeriod(byte channelNumber, short channelPeriod) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSetChannelPeriod(channelNumber, channelPeriod)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT set channel rf freq. - * - * @param channelNumber the channel number - * @param radioFrequency the radio frequency - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSetChannelRFFreq(byte channelNumber, byte radioFrequency) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSetChannelRFFreq(channelNumber, radioFrequency)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT set channel search timeout. - * - * @param channelNumber the channel number - * @param searchTimeout the search timeout - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSetChannelSearchTimeout(byte channelNumber, byte searchTimeout) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSetChannelSearchTimeout(channelNumber, searchTimeout)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT set low priority channel search timeout. - * - * @param channelNumber the channel number - * @param searchTimeout the search timeout - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSetLowPriorityChannelSearchTimeout(byte channelNumber, byte searchTimeout) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSetLowPriorityChannelSearchTimeout(channelNumber, searchTimeout)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT set proximity search. - * - * @param channelNumber the channel number - * @param searchThreshold the search threshold - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSetProximitySearch(byte channelNumber, byte searchThreshold) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSetProximitySearch(channelNumber, searchThreshold)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT set channel transmit power - * @param channelNumber the channel number - * @param txPower the transmit power level - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSetChannelTxPower(byte channelNumber, byte txPower) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSetChannelTxPower(channelNumber, txPower)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT add channel id. - * - * @param channelNumber the channel number - * @param deviceNumber the device number - * @param deviceType the device type - * @param txType the tx type - * @param listIndex the list index - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTAddChannelId(byte channelNumber, short deviceNumber, byte deviceType, byte txType, byte listIndex) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTAddChannelId(channelNumber, deviceNumber, deviceType, txType, listIndex)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT config list. - * - * @param channelNumber the channel number - * @param listSize the list size - * @param exclude the exclude - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTConfigList(byte channelNumber, byte listSize, byte exclude) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTConfigList(channelNumber, listSize, exclude)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT config event buffering. - * - * @param screenOnFlushTimerInterval the screen on flush timer interval - * @param screenOnFlushBufferThreshold the screen on flush buffer threshold - * @param screenOffFlushTimerInterval the screen off flush timer interval - * @param screenOffFlushBufferThreshold the screen off flush buffer threshold - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.3 - */ - public void ANTConfigEventBuffering(short screenOnFlushTimerInterval, short screenOnFlushBufferThreshold, short screenOffFlushTimerInterval, short screenOffFlushBufferThreshold) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTConfigEventBuffering((int)screenOnFlushTimerInterval, (int)screenOnFlushBufferThreshold, (int)screenOffFlushTimerInterval, (int)screenOffFlushBufferThreshold)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT disable event buffering. - * - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.1 - */ - public void ANTDisableEventBuffering() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTDisableEventBuffering()) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT open channel. - * - * @param channelNumber the channel number - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTOpenChannel(byte channelNumber) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTOpenChannel(channelNumber)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT close channel. - * - * @param channelNumber the channel number - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTCloseChannel(byte channelNumber) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTCloseChannel(channelNumber)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT request message. - * - * @param channelNumber the channel number - * @param messageID the message id - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTRequestMessage(byte channelNumber, byte messageID) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTRequestMessage(channelNumber, messageID)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT send broadcast data. - * - * @param channelNumber the channel number - * @param txBuffer the tx buffer - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSendBroadcastData(byte channelNumber, byte[] txBuffer) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSendBroadcastData(channelNumber, txBuffer)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT send acknowledged data. - * - * @param channelNumber the channel number - * @param txBuffer the tx buffer - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSendAcknowledgedData(byte channelNumber, byte[] txBuffer) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSendAcknowledgedData(channelNumber, txBuffer)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT send burst transfer packet. - * - * @param control the control - * @param txBuffer the tx buffer - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public void ANTSendBurstTransferPacket(byte control, byte[] txBuffer) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - if(!sAntReceiver.ANTSendBurstTransferPacket(control, txBuffer)) - { - throw new AntInterfaceException(); - } - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Transmits the given data on channelNumber as part of a burst message. - * - * @param channelNumber Which channel to transmit on. - * @param txBuffer The data to send. - * @return The number of bytes still to be sent (approximately). 0 if success. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - */ - public int ANTSendBurstTransfer(byte channelNumber, byte[] txBuffer) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.ANTSendBurstTransfer(channelNumber, txBuffer); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * ANT send partial burst. - * - * @param channelNumber the channel number - * @param txBuffer the tx buffer - * @param initialPacket the initial packet - * @param containsEndOfBurst the contains end of burst - * @return The number of bytes still to be sent (approximately). 0 if success. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.0 - */ - public int ANTSendPartialBurst(byte channelNumber, byte[] txBuffer, int initialPacket, boolean containsEndOfBurst) throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.ANTTransmitBurst(channelNumber, txBuffer, initialPacket, containsEndOfBurst); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Returns the version code (eg. 1) of ANTLib used by the ANT application service - * - * @return the service library version code, or 0 on error. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.2 - */ - public int getServiceLibraryVersionCode() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - if(mServiceLibraryVersionCode == 0) - { - try - { - mServiceLibraryVersionCode = sAntReceiver.getServiceLibraryVersionCode(); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - return mServiceLibraryVersionCode; - } - - /** - * Returns the version name (eg "1.0") of ANTLib used by the ANT application service - * - * @return the service library version name, or null on error. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.2 - */ - public String getServiceLibraryVersionName() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.getServiceLibraryVersionName(); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Take control of the ANT Radio. - * - * @return True if control has been granted, false if another application has control or the request failed. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.5 - */ - public boolean claimInterface() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.claimInterface(); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Give up control of the ANT Radio. - * - * @return True if control has been given up, false if this application did not have control. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.5 - */ - public boolean releaseInterface() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.releaseInterface(); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Claims the interface if it is available. If not the user will be prompted (on the notification bar) if a force claim should be done. - * If the ANT Interface is claimed, an AntInterfaceIntent.ANT_INTERFACE_CLAIMED_ACTION intent will be sent, with the current applications pid. - * - * @param appName The name if this application, to show to the user. - * @returns false if a claim interface request notification already exists. - * @throws IllegalArgumentException - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.5 - */ - public boolean requestForceClaimInterface(String appName) throws AntInterfaceException - { - if((null == appName) || ("".equals(appName))) - { - throw new IllegalArgumentException(); - } - - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.requestForceClaimInterface(appName); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Clears the notification asking the user if they would like to seize control of the ANT Radio. - * - * @returns false if this process is not requesting to claim the interface. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.5 - */ - public boolean stopRequestForceClaimInterface() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.stopRequestForceClaimInterface(); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Check if the calling application has control of the ANT Radio. - * - * @return True if control is currently granted. - * @throws AntInterfaceException - * @throws AntServiceNotConnectedException - * @throws AntRemoteException - * @since 1.5 - */ - public boolean hasClaimedInterface() throws AntInterfaceException - { - if(!sServiceConnected) - { - throw new AntServiceNotConnectedException(); - } - - try - { - return sAntReceiver.hasClaimedInterface(); - } - catch(RemoteException e) - { - throw new AntRemoteException(e); - } - } - - /** - * Check if this device has support for ANT. - * - * @return True if the device supports ANT (may still require ANT Radio Service be installed). - * @since 1.5 - */ - public static boolean hasAntSupport(Context pContext) - { - if(!mCheckedAntSupported) - { - mAntSupported = Arrays.asList(pContext.getPackageManager().getSystemSharedLibraryNames()).contains(ANT_LIBRARY_NAME); - mCheckedAntSupported = true; - } - - return mAntSupported; - } -} diff --git a/MyTracks/src/com/dsi/ant/AntInterfaceIntent.java b/MyTracks/src/com/dsi/ant/AntInterfaceIntent.java deleted file mode 100644 index 7834e9daa..000000000 --- a/MyTracks/src/com/dsi/ant/AntInterfaceIntent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2010 Dynastream Innovations Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.dsi.ant; - -/** - * Manages the ANT Interface - * - * @hide - */ -public interface AntInterfaceIntent { - - public static final String STATUS = "com.dsi.ant.rx.intent.STATUS"; - public static final String ANT_MESSAGE = "com.dsi.ant.intent.ANT_MESSAGE"; - public static final String ANT_INTERFACE_CLAIMED_PID = "com.dsi.ant.intent.ANT_INTERFACE_CLAIMED_PID"; - - public static final String ANT_ENABLED_ACTION = "com.dsi.ant.intent.action.ANT_ENABLED"; - public static final String ANT_DISABLED_ACTION = "com.dsi.ant.intent.action.ANT_DISABLED"; - public static final String ANT_RESET_ACTION = "com.dsi.ant.intent.action.ANT_RESET"; - - public static final String ANT_INTERFACE_CLAIMED_ACTION = "com.dsi.ant.intent.action.ANT_INTERFACE_CLAIMED_ACTION"; - - public static final String ANT_RX_MESSAGE_ACTION = "com.dsi.ant.intent.action.ANT_RX_MESSAGE_ACTION"; - -} diff --git a/MyTracks/src/com/dsi/ant/AntMesg.java b/MyTracks/src/com/dsi/ant/AntMesg.java deleted file mode 100644 index cf2ae70d9..000000000 --- a/MyTracks/src/com/dsi/ant/AntMesg.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2010 Dynastream Innovations Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.dsi.ant; - -/** - * Public API for controlling the Ant Service. - * AntMesg contains definitions for ANT message IDs - * - * @hide - */ -public class AntMesg { - - ///////////////////////////////////////////////////////////////////////////// - // HCI VS Message Format - // Messages are in the format: - // - // Outgoing ANT messages (host -> ANT chip) - // 01 D1 FD XX YY YY II JJ ------ - // ^ ^ ^ ^ - // | HCI framing | | ANT Mesg | - // - // where: 01 is the 1 byte HCI packet Identifier (HCI Command packet) - // D1 FD is the 2 byte HCI op code (0xFDD1 stored in little endian) - // XX is the 1 byte Length of all parameters in bytes (number of bytes in the HCI packet after this byte) - // YY YY is the 2 byte Parameter describing the length of the entire ANT message (II JJ ------) stored in little endian - // II is the 1 byte size of the ANT message (0-249) - // JJ is the 1 byte ID of the ANT message (1-255, 0 is invalid) - // ------ is the data of the ANT message (0-249 bytes of data) - // - // Incoming HCI Command Complete for ANT message command (host <- ANT chip) - // 04 0E 04 01 D1 FD ZZ - // - // where: 04 is the 1 byte HCI packet Identifier (HCI Event packet) - // 0E is the 1 byte HCI event (Command Complete) - // 04 is the 1 byte Length of all parameters in bytes (there are 4 bytes) - // 01 is the 1 byte Number of parameters in the packet (there is 1 parameter) - // D1 FD is the 2 byte HCI Op code of the command (0xFDD1 stored in little endian) - // ZZ is the 1 byte response to the command (0x00 - Command Successful - // 0x1F - Returned if the receive message queue of the ANT chip is full, the command should be retried - // Other - Any other non-zero response code indicates an error) - // - // Incoming ANT messages (host <- ANT chip) - // 04 FF XX 00 05 YY YY II JJ ------ - // ^ ^ ^ ^ - // | HCI framing | | ANT Mesg | - // - // where: 04 is the 1 byte HCI packet Identifier (HCI Event packet) - // FF is the 1 byte HCI event code (0xFF Vendor Specific event) - // XX is the 1 byte Length of all parameters in bytes (number of bytes in the HCI packet after this byte) - // 00 05 is the 2 byte vendor specific event code for ANT messages (0x0500 stored in little endian) - // YY YY is the 2 byte Parameter describing the length of the entire ANT message (II JJ ------) stored in little endian - // II is the 1 byte size of the ANT message (0-249) - // JJ is the 1 byte ID of the ANT message (1-255, 0 is invalid) - // ------ is the data of the ANT message (0-249 bytes of data) - // - ///////////////////////////////////////////////////////////////////////////// - - public static final byte MESG_SYNC_SIZE =((byte)0); // Ant messages are embedded in HCI messages we do not include a sync byte - public static final byte MESG_SIZE_SIZE =((byte)1); - public static final byte MESG_ID_SIZE =((byte)1); - public static final byte MESG_CHANNEL_NUM_SIZE =((byte)1); - public static final byte MESG_EXT_MESG_BF_SIZE =((byte)1); // NOTE: this could increase in the future - public static final byte MESG_CHECKSUM_SIZE =((byte)0); // Ant messages are embedded in HCI messages we do not include a checksum - public static final byte MESG_DATA_SIZE =((byte)9); - - // The largest serial message is an ANT data message with all of the extended fields - public static final byte MESG_ANT_MAX_PAYLOAD_SIZE =AntDefine.ANT_STANDARD_DATA_PAYLOAD_SIZE; - - public static final byte MESG_MAX_EXT_DATA_SIZE =(AntDefine.ANT_EXT_MESG_DEVICE_ID_FIELD_SIZE + AntDefine.ANT_EXT_STRING_SIZE); // ANT device ID (4 bytes) + Padding for ANT EXT string size(19 bytes) - - public static final byte MESG_MAX_DATA_SIZE =(MESG_ANT_MAX_PAYLOAD_SIZE + MESG_EXT_MESG_BF_SIZE + MESG_MAX_EXT_DATA_SIZE); // ANT data payload (8 bytes) + extended bitfield (1 byte) + extended data (10 bytes) - public static final byte MESG_MAX_SIZE_VALUE =(MESG_MAX_DATA_SIZE + MESG_CHANNEL_NUM_SIZE); // this is the maximum value that the serial message size value is allowed to be - public static final byte MESG_BUFFER_SIZE =(MESG_SIZE_SIZE + MESG_ID_SIZE + MESG_CHANNEL_NUM_SIZE + MESG_MAX_DATA_SIZE + MESG_CHECKSUM_SIZE); - public static final byte MESG_FRAMED_SIZE =(MESG_ID_SIZE + MESG_CHANNEL_NUM_SIZE + MESG_MAX_DATA_SIZE); - public static final byte MESG_HEADER_SIZE =(MESG_SYNC_SIZE + MESG_SIZE_SIZE + MESG_ID_SIZE); - public static final byte MESG_FRAME_SIZE =(MESG_HEADER_SIZE + MESG_CHECKSUM_SIZE); - public static final byte MESG_MAX_SIZE =(MESG_MAX_DATA_SIZE + MESG_FRAME_SIZE); - - public static final byte MESG_SIZE_OFFSET =(MESG_SYNC_SIZE); - public static final byte MESG_ID_OFFSET =(MESG_SYNC_SIZE + MESG_SIZE_SIZE); - public static final byte MESG_DATA_OFFSET =(MESG_HEADER_SIZE); - public static final byte MESG_RECOMMENDED_BUFFER_SIZE =((byte) 64); // This is the recommended size for serial message buffers if there are no RAM restrictions on the system - - ////////////////////////////////////////////// - // Message ID's - ////////////////////////////////////////////// - public static final byte MESG_INVALID_ID =((byte)0x00); - public static final byte MESG_EVENT_ID =((byte)0x01); - - public static final byte MESG_VERSION_ID =((byte)0x3E); - public static final byte MESG_RESPONSE_EVENT_ID =((byte)0x40); - - public static final byte MESG_UNASSIGN_CHANNEL_ID =((byte)0x41); - public static final byte MESG_ASSIGN_CHANNEL_ID =((byte)0x42); - public static final byte MESG_CHANNEL_MESG_PERIOD_ID =((byte)0x43); - public static final byte MESG_CHANNEL_SEARCH_TIMEOUT_ID =((byte)0x44); - public static final byte MESG_CHANNEL_RADIO_FREQ_ID =((byte)0x45); - public static final byte MESG_NETWORK_KEY_ID =((byte)0x46); - public static final byte MESG_RADIO_TX_POWER_ID =((byte)0x47); - public static final byte MESG_RADIO_CW_MODE_ID =((byte)0x48); - - public static final byte MESG_SYSTEM_RESET_ID =((byte)0x4A); - public static final byte MESG_OPEN_CHANNEL_ID =((byte)0x4B); - public static final byte MESG_CLOSE_CHANNEL_ID =((byte)0x4C); - public static final byte MESG_REQUEST_ID =((byte)0x4D); - - public static final byte MESG_BROADCAST_DATA_ID =((byte)0x4E); - public static final byte MESG_ACKNOWLEDGED_DATA_ID =((byte)0x4F); - public static final byte MESG_BURST_DATA_ID =((byte)0x50); - - public static final byte MESG_CHANNEL_ID_ID =((byte)0x51); - public static final byte MESG_CHANNEL_STATUS_ID =((byte)0x52); - public static final byte MESG_RADIO_CW_INIT_ID =((byte)0x53); - public static final byte MESG_CAPABILITIES_ID =((byte)0x54); - - public static final byte MESG_STACKLIMIT_ID =((byte)0x55); - - public static final byte MESG_SCRIPT_DATA_ID =((byte)0x56); - public static final byte MESG_SCRIPT_CMD_ID =((byte)0x57); - - public static final byte MESG_ID_LIST_ADD_ID =((byte)0x59); - public static final byte MESG_ID_LIST_CONFIG_ID =((byte)0x5A); - public static final byte MESG_OPEN_RX_SCAN_ID =((byte)0x5B); - - public static final byte MESG_EXT_CHANNEL_RADIO_FREQ_ID =((byte)0x5C); // OBSOLETE: (for 905 radio) - public static final byte MESG_EXT_BROADCAST_DATA_ID =((byte)0x5D); - public static final byte MESG_EXT_ACKNOWLEDGED_DATA_ID =((byte)0x5E); - public static final byte MESG_EXT_BURST_DATA_ID =((byte)0x5F); - - public static final byte MESG_CHANNEL_RADIO_TX_POWER_ID =((byte)0x60); - public static final byte MESG_GET_SERIAL_NUM_ID =((byte)0x61); - public static final byte MESG_GET_TEMP_CAL_ID =((byte)0x62); - public static final byte MESG_SET_LP_SEARCH_TIMEOUT_ID =((byte)0x63); - public static final byte MESG_SET_TX_SEARCH_ON_NEXT_ID =((byte)0x64); - public static final byte MESG_SERIAL_NUM_SET_CHANNEL_ID_ID =((byte)0x65); - public static final byte MESG_RX_EXT_MESGS_ENABLE_ID =((byte)0x66); - public static final byte MESG_RADIO_CONFIG_ALWAYS_ID =((byte)0x67); - public static final byte MESG_ENABLE_LED_FLASH_ID =((byte)0x68); - - public static final byte MESG_XTAL_ENABLE_ID =((byte)0x6D); - - public static final byte MESG_STARTUP_MESG_ID =((byte)0x6F); - public static final byte MESG_AUTO_FREQ_CONFIG_ID =((byte)0x70); - public static final byte MESG_PROX_SEARCH_CONFIG_ID =((byte)0x71); - public static final byte MESG_EVENT_BUFFERING_CONFIG_ID =((byte)0x74); - - - public static final byte MESG_CUBE_CMD_ID =((byte)0x80); - - public static final byte MESG_GET_PIN_DIODE_CONTROL_ID =((byte)0x8D); - public static final byte MESG_PIN_DIODE_CONTROL_ID =((byte)0x8E); - public static final byte MESG_FIT1_SET_AGC_ID =((byte)0x8F); - - public static final byte MESG_FIT1_SET_EQUIP_STATE_ID =((byte)0x91); // *** CONFLICT: w/ Sensrcore, Fit1 will never have sensrcore enabled - - // Sensrcore Messages - public static final byte MESG_SET_CHANNEL_INPUT_MASK_ID =((byte)0x90); - public static final byte MESG_SET_CHANNEL_DATA_TYPE_ID =((byte)0x91); - public static final byte MESG_READ_PINS_FOR_SECT_ID =((byte)0x92); - public static final byte MESG_TIMER_SELECT_ID =((byte)0x93); - public static final byte MESG_ATOD_SETTINGS_ID =((byte)0x94); - public static final byte MESG_SET_SHARED_ADDRESS_ID =((byte)0x95); - public static final byte MESG_ATOD_EXTERNAL_ENABLE_ID =((byte)0x96); - public static final byte MESG_ATOD_PIN_SETUP_ID =((byte)0x97); - public static final byte MESG_SETUP_ALARM_ID =((byte)0x98); - public static final byte MESG_ALARM_VARIABLE_MODIFY_TEST_ID =((byte)0x99); - public static final byte MESG_PARTIAL_RESET_ID =((byte)0x9A); - public static final byte MESG_OVERWRITE_TEMP_CAL_ID =((byte)0x9B); - public static final byte MESG_SERIAL_PASSTHRU_SETTINGS_ID =((byte)0x9C); - - public static final byte MESG_BIST_ID =((byte)0xAA); - - public static final byte MESG_UNLOCK_INTERFACE_ID =((byte)0xAD); - public static final byte MESG_SERIAL_ERROR_ID =((byte)0xAE); - public static final byte MESG_SET_ID_STRING_ID =((byte)0xAF); - - public static final byte MESG_PORT_GET_IO_STATE_ID =((byte)0xB4); - public static final byte MESG_PORT_SET_IO_STATE_ID =((byte)0xB5); - - public static final byte MESG_SLEEP_ID =((byte)0xC5); - public static final byte MESG_GET_GRMN_ESN_ID =((byte)0xC6); - public static final byte MESG_SET_USB_INFO_ID =((byte)0xC7); - - public static final byte MESG_COMMAND_COMPLETE_RESPONSE_ID =((byte)0xC8); - - ////////////////////////////////////////////// - // Command complete results - ////////////////////////////////////////////// - public static final byte MESG_COMMAND_COMPLETE_SUCCESS =((byte)0x00); - public static final byte MESG_COMMAND_COMPLETE_RETRY =((byte)0x1F); - - ////////////////////////////////////////////// - // Message Sizes - ////////////////////////////////////////////// - public static final byte MESG_INVALID_SIZE =((byte)0); - - public static final byte MESG_VERSION_SIZE =((byte)13); - public static final byte MESG_RESPONSE_EVENT_SIZE =((byte)3); - public static final byte MESG_CHANNEL_STATUS_SIZE =((byte)2); - - public static final byte MESG_UNASSIGN_CHANNEL_SIZE =((byte)1); - public static final byte MESG_ASSIGN_CHANNEL_SIZE =((byte)3); - public static final byte MESG_CHANNEL_ID_SIZE =((byte)5); - public static final byte MESG_CHANNEL_MESG_PERIOD_SIZE =((byte)3); - public static final byte MESG_CHANNEL_SEARCH_TIMEOUT_SIZE =((byte)2); - public static final byte MESG_CHANNEL_RADIO_FREQ_SIZE =((byte)2); - public static final byte MESG_CHANNEL_RADIO_TX_POWER_SIZE =((byte)2); - public static final byte MESG_NETWORK_KEY_SIZE =((byte)9); - public static final byte MESG_RADIO_TX_POWER_SIZE =((byte)2); - public static final byte MESG_RADIO_CW_MODE_SIZE =((byte)3); - public static final byte MESG_RADIO_CW_INIT_SIZE =((byte)1); - - public static final byte MESG_SYSTEM_RESET_SIZE =((byte)1); - public static final byte MESG_OPEN_CHANNEL_SIZE =((byte)1); - public static final byte MESG_CLOSE_CHANNEL_SIZE =((byte)1); - public static final byte MESG_REQUEST_SIZE =((byte)2); - - public static final byte MESG_CAPABILITIES_SIZE =((byte)6); - public static final byte MESG_STACKLIMIT_SIZE =((byte)2); - - public static final byte MESG_SCRIPT_DATA_SIZE =((byte)10); - public static final byte MESG_SCRIPT_CMD_SIZE =((byte)3); - - public static final byte MESG_ID_LIST_ADD_SIZE =((byte)6); - public static final byte MESG_ID_LIST_CONFIG_SIZE =((byte)3); - public static final byte MESG_OPEN_RX_SCAN_SIZE =((byte)1); - public static final byte MESG_EXT_CHANNEL_RADIO_FREQ_SIZE =((byte)3); - - public static final byte MESG_RADIO_CONFIG_ALWAYS_SIZE =((byte)2); - public static final byte MESG_RX_EXT_MESGS_ENABLE_SIZE =((byte)2); - public static final byte MESG_SET_TX_SEARCH_ON_NEXT_SIZE =((byte)2); - public static final byte MESG_SET_LP_SEARCH_TIMEOUT_SIZE =((byte)2); - - public static final byte MESG_SERIAL_NUM_SET_CHANNEL_ID_SIZE =((byte)3); - public static final byte MESG_ENABLE_LED_FLASH_SIZE =((byte)2); - public static final byte MESG_GET_SERIAL_NUM_SIZE =((byte)4); - public static final byte MESG_GET_TEMP_CAL_SIZE =((byte)4); - - public static final byte MESG_XTAL_ENABLE_SIZE =((byte)1); - public static final byte MESG_STARTUP_MESG_SIZE =((byte)1); - public static final byte MESG_AUTO_FREQ_CONFIG_SIZE =((byte)4); - public static final byte MESG_PROX_SEARCH_CONFIG_SIZE =((byte)2); - - public static final byte MESG_GET_PIN_DIODE_CONTROL_SIZE =((byte)1); - public static final byte MESG_PIN_DIODE_CONTROL_ID_SIZE =((byte)2); - public static final byte MESG_FIT1_SET_EQUIP_STATE_SIZE =((byte)2); - public static final byte MESG_FIT1_SET_AGC_SIZE =((byte)3); - - public static final byte MESG_BIST_SIZE =((byte)6); - public static final byte MESG_UNLOCK_INTERFACE_SIZE =((byte)1); - public static final byte MESG_SET_SHARED_ADDRESS_SIZE =((byte)3); - - public static final byte MESG_GET_GRMN_ESN_SIZE =((byte)5); - - public static final byte MESG_PORT_SET_IO_STATE_SIZE =((byte)5); - - public static final byte MESG_EVENT_BUFFERING_CONFIG_SIZE =((byte)6); - - public static final byte MESG_SLEEP_SIZE =((byte)1); - - - public static final byte MESG_EXT_DATA_SIZE =((byte)13); - - protected AntMesg() - { } -} diff --git a/MyTracks/src/com/dsi/ant/IAnt.aidl b/MyTracks/src/com/dsi/ant/IAnt.aidl deleted file mode 100644 index 8ee999070..000000000 --- a/MyTracks/src/com/dsi/ant/IAnt.aidl +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2010 Dynastream Innovations Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.dsi.ant; - -/** - * The Android Ant API is not finalized, and *will* be updated and expanded. - * This is the base level ANT messaging API and gives any application full - * control over the ANT radio HW. Caution should be exercised when using - * this interface. - * - * Public API for controlling the Ant Service. - * - * {@hide} - */ -interface IAnt { -// Since version 1 (1.0): - boolean enable(); - boolean disable(); - boolean isEnabled(); - - boolean ANTTxMessage(in byte[] message); - - boolean ANTResetSystem(); - boolean ANTUnassignChannel(byte channelNumber); - boolean ANTAssignChannel(byte channelNumber, byte channelType, byte networkNumber); - boolean ANTSetChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType); - boolean ANTSetChannelPeriod(byte channelNumber, int channelPeriod); - boolean ANTSetChannelRFFreq(byte channelNumber, byte radioFrequency); - boolean ANTSetChannelSearchTimeout(byte channelNumber, byte searchTimeout); - boolean ANTSetLowPriorityChannelSearchTimeout(byte channelNumber, byte searchTimeout); - boolean ANTSetProximitySearch(byte channelNumber, byte searchThreshold); - boolean ANTSetChannelTxPower(byte channelNumber, byte txPower); - boolean ANTAddChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType, byte listIndex); - boolean ANTConfigList(byte channelNumber, byte listSize, byte exclude); - - boolean ANTOpenChannel(byte channelNumber); - boolean ANTCloseChannel(byte channelNumber); - - boolean ANTRequestMessage(byte channelNumber, byte messageID); - boolean ANTSendBroadcastData(byte channelNumber, in byte[] txBuffer); - boolean ANTSendAcknowledgedData(byte channelNumber, in byte[] txBuffer); - - boolean ANTSendBurstTransferPacket(byte control, in byte[] txBuffer); - - int ANTSendBurstTransfer(byte channelNumber, in byte[] txBuffer); - int ANTTransmitBurst(byte channelNumber, in byte[] txBuffer, int initialPacket, boolean containsEndOfBurst); - -// Since version 4 (1.3): - boolean ANTConfigEventBuffering(int screenOnFlushTimerInterval, int screenOnFlushBufferThreshold, int screenOffFlushTimerInterval, int screenOffFlushBufferThreshold); - -// Since version 2 (1.1): - boolean ANTDisableEventBuffering(); - -// Since version 3 (1.2): - int getServiceLibraryVersionCode(); - String getServiceLibraryVersionName(); -} diff --git a/MyTracks/src/com/dsi/ant/IAnt_6.aidl b/MyTracks/src/com/dsi/ant/IAnt_6.aidl deleted file mode 100644 index 4caccbeb7..000000000 --- a/MyTracks/src/com/dsi/ant/IAnt_6.aidl +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2011 Dynastream Innovations Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.dsi.ant; - -/** - * The Android Ant API is not finalized, and *will* be updated and expanded. - * This is the base level ANT messaging API and gives any application full - * control over the ANT radio HW. Caution should be exercised when using - * this interface. - * - * Public API for controlling the Ant Service. - * - * {@hide} - */ -interface IAnt_6 { -// Since version 1 (1.0): - boolean enable(); - boolean disable(); - boolean isEnabled(); - - boolean ANTTxMessage(in byte[] message); - - boolean ANTResetSystem(); - boolean ANTUnassignChannel(byte channelNumber); - boolean ANTAssignChannel(byte channelNumber, byte channelType, byte networkNumber); - boolean ANTSetChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType); - boolean ANTSetChannelPeriod(byte channelNumber, int channelPeriod); - boolean ANTSetChannelRFFreq(byte channelNumber, byte radioFrequency); - boolean ANTSetChannelSearchTimeout(byte channelNumber, byte searchTimeout); - boolean ANTSetLowPriorityChannelSearchTimeout(byte channelNumber, byte searchTimeout); - boolean ANTSetProximitySearch(byte channelNumber, byte searchThreshold); - boolean ANTSetChannelTxPower(byte channelNumber, byte txPower); - boolean ANTAddChannelId(byte channelNumber, int deviceNumber, byte deviceType, byte txType, byte listIndex); - boolean ANTConfigList(byte channelNumber, byte listSize, byte exclude); - - boolean ANTOpenChannel(byte channelNumber); - boolean ANTCloseChannel(byte channelNumber); - - boolean ANTRequestMessage(byte channelNumber, byte messageID); - boolean ANTSendBroadcastData(byte channelNumber, in byte[] txBuffer); - boolean ANTSendAcknowledgedData(byte channelNumber, in byte[] txBuffer); - - boolean ANTSendBurstTransferPacket(byte control, in byte[] txBuffer); - - int ANTSendBurstTransfer(byte channelNumber, in byte[] txBuffer); - int ANTTransmitBurst(byte channelNumber, in byte[] txBuffer, int initialPacket, boolean containsEndOfBurst); - -// Since version 4 (1.3): - boolean ANTConfigEventBuffering(int screenOnFlushTimerInterval, int screenOnFlushBufferThreshold, int screenOffFlushTimerInterval, int screenOffFlushBufferThreshold); - -// Since version 2 (1.1): - boolean ANTDisableEventBuffering(); - -// Since version 3 (1.2): - int getServiceLibraryVersionCode(); - String getServiceLibraryVersionName(); - -// Since version 6 (1.5): - boolean claimInterface(); - boolean requestForceClaimInterface(String appName); - boolean stopRequestForceClaimInterface(); - boolean releaseInterface(); - boolean hasClaimedInterface(); -} diff --git a/MyTracks/src/com/dsi/ant/IServiceSettings.aidl b/MyTracks/src/com/dsi/ant/IServiceSettings.aidl deleted file mode 100644 index 3d0cf61c8..000000000 --- a/MyTracks/src/com/dsi/ant/IServiceSettings.aidl +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2010 Dynastream Innovations Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.dsi.ant; - -/** - * - * API for configuring the non-ANT components of the ANT Service. - * - * {@hide} - */ -interface IServiceSettings { - void debugLogging(boolean debug); - - boolean setNumCombinedBurstPackets(int numPackets); - int getNumCombinedBurstPackets(); -} diff --git a/MyTracks/src/com/dsi/ant/Version.java b/MyTracks/src/com/dsi/ant/Version.java deleted file mode 100644 index 7d7cb8bd5..000000000 --- a/MyTracks/src/com/dsi/ant/Version.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2011 Dynastream Innovations Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.dsi.ant; - - - -/** - * Defines version numbers - * - * @hide - */ -public class Version { - - ////////////////////////////////////////////// - // Library Version Information - ////////////////////////////////////////////// - public static final int ANT_LIBRARY_VERSION_CODE = 6; - public static final int ANT_LIBRARY_VERSION_MAJOR = 2; - public static final int ANT_LIBRARY_VERSION_MINOR = 0; - public static final String ANT_LIBRARY_VERSION_NAME = String.valueOf(ANT_LIBRARY_VERSION_MAJOR) + "." + String.valueOf(ANT_LIBRARY_VERSION_MINOR); - -} \ No newline at end of file diff --git a/MyTracks/src/com/dsi/ant/exception/AntInterfaceException.java b/MyTracks/src/com/dsi/ant/exception/AntInterfaceException.java deleted file mode 100644 index 164374e4a..000000000 --- a/MyTracks/src/com/dsi/ant/exception/AntInterfaceException.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dsi.ant.exception; - -public class AntInterfaceException extends Exception -{ - - /** - * - */ - private static final long serialVersionUID = -7278855366167722274L; - - public AntInterfaceException() - { - this("Unknown ANT Interface error"); - } - - public AntInterfaceException(String string) - { - super(string); - } -} diff --git a/MyTracks/src/com/dsi/ant/exception/AntRemoteException.java b/MyTracks/src/com/dsi/ant/exception/AntRemoteException.java deleted file mode 100644 index 960740f1c..000000000 --- a/MyTracks/src/com/dsi/ant/exception/AntRemoteException.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dsi.ant.exception; - -import android.os.RemoteException; - -public class AntRemoteException extends AntInterfaceException -{ - /** - * - */ - private static final long serialVersionUID = 8950974759973459561L; - - public AntRemoteException(RemoteException e) - { - this("ANT Interface error, ANT Radio Service remote error: "+e.toString(), e); - } - - public AntRemoteException(String string, RemoteException e) - { - super(string); - - this.initCause(e); - } -} diff --git a/MyTracks/src/com/dsi/ant/exception/AntServiceNotConnectedException.java b/MyTracks/src/com/dsi/ant/exception/AntServiceNotConnectedException.java deleted file mode 100644 index fc131cf8f..000000000 --- a/MyTracks/src/com/dsi/ant/exception/AntServiceNotConnectedException.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dsi.ant.exception; - -public class AntServiceNotConnectedException extends AntInterfaceException -{ - /** - * - */ - private static final long serialVersionUID = -2085081032170129309L; - - public AntServiceNotConnectedException() - { - this("ANT Interface error, ANT Radio Service not connected."); - } - - public AntServiceNotConnectedException(String string) - { - super(string); - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/AntPreference.java b/MyTracks/src/com/google/android/apps/mytracks/AntPreference.java deleted file mode 100644 index 687facde6..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/AntPreference.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2010 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks; - -import com.google.android.maps.mytracks.R; - -import android.content.Context; -import android.preference.Preference; -import android.util.AttributeSet; - -/** - * A preference for an ANT device pairing. - * Currently this shows the ID and lets the user clear that ID for future pairing. - * TODO: Support pairing from this preference. - * - * @author Sandor Dornbush - */ -public class AntPreference extends Preference { - - private final static int DEFAULT_PERSISTEDINT = 0; - - public AntPreference(Context context) { - super(context); - init(); - } - - public AntPreference(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - private void init() { - int sensorId = getPersistedInt(AntPreference.DEFAULT_PERSISTEDINT); - if (sensorId == 0) { - setSummary(R.string.settings_sensor_ant_not_paired); - } else { - setSummary(getContext().getString(R.string.settings_sensor_ant_paired, sensorId)); - } - - // Add actions to allow repairing. - setOnPreferenceClickListener( - new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - AntPreference.this.persistInt(0); - setSummary(R.string.settings_sensor_ant_not_paired); - return true; - } - }); - } -} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothSensorManager.java index a8b8ce0af..fb12c8f9a 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothSensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/BluetoothSensorManager.java @@ -96,8 +96,7 @@ public class BluetoothSensorManager extends SensorManager { case BluetoothConnectionManager.MESSAGE_DEVICE_NAME: String deviceName = message.getData() .getString(BluetoothConnectionManager.KEY_DEVICE_NAME); - Toast.makeText(context, - context.getString(R.string.settings_sensor_bluetooth_connected, deviceName), + Toast.makeText(context, context.getString(R.string.settings_sensor_connected, deviceName), Toast.LENGTH_SHORT).show(); break; case BluetoothConnectionManager.MESSAGE_READ: diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManagerFactory.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManagerFactory.java index 0f651fe70..d4e16bba1 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManagerFactory.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/SensorManagerFactory.java @@ -16,8 +16,7 @@ package com.google.android.apps.mytracks.services.sensors; -import com.google.android.apps.mytracks.services.sensors.ant.AntDirectSensorManager; -import com.google.android.apps.mytracks.services.sensors.ant.AntSrmBridgeSensorManager; +import com.google.android.apps.mytracks.services.sensors.ant.AntSensorManager; import com.google.android.apps.mytracks.util.PreferencesUtils; import com.google.android.maps.mytracks.R; @@ -98,9 +97,7 @@ public class SensorManagerFactory { context, R.string.sensor_type_key, sensorTypeValueNone); if (sensorType.equals(context.getString(R.string.sensor_type_value_ant))) { - return new AntDirectSensorManager(context); - } else if (sensorType.equals(context.getString(R.string.sensor_type_value_srm_ant_bridge))) { - return new AntSrmBridgeSensorManager(context); + return new AntSensorManager(context); } else if (sensorType.equals(context.getString(R.string.sensor_type_value_zephyr))) { return new ZephyrSensorManager(context); } else if (sensorType.equals(context.getString(R.string.sensor_type_value_polar))) { diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelIdMessage.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelIdMessage.java deleted file mode 100644 index 2d866fe1c..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelIdMessage.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -/** - * This class decodes and encapsulates an ANT Channel ID message. - * (ANT Message ID 0x51, Protocol & Usage guide v4.2 section 9.5.7.2) - * - * @author Matthew Simmons - */ -public class AntChannelIdMessage extends AntMessage { - private byte channelNumber; - private short deviceNumber; - private byte deviceTypeId; - private byte transmissionType; - - public AntChannelIdMessage(byte[] messageData) { - channelNumber = messageData[0]; - deviceNumber = decodeShort(messageData[1], messageData[2]); - deviceTypeId = messageData[3]; - transmissionType = messageData[4]; - } - - /** Returns the channel number */ - public byte getChannelNumber() { - return channelNumber; - } - - /** Returns the device number */ - public short getDeviceNumber() { - return deviceNumber; - } - - /** Returns the device type */ - public byte getDeviceTypeId() { - return deviceTypeId; - } - - /** Returns the transmission type */ - public byte getTransmissionType() { - return transmissionType; - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelResponseMessage.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelResponseMessage.java deleted file mode 100644 index a29a0757d..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelResponseMessage.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -/** - * This class decodes and encapsulates an ANT Channel Response / Event message. - * (ANT Message ID 0x40, Protocol & Usage guide v4.2 section 9.5.6.1) - * - * @author Matthew Simmons - */ -public class AntChannelResponseMessage extends AntMessage { - private byte channelNumber; - private byte messageId; - private byte messageCode; - - public AntChannelResponseMessage(byte[] messageData) { - channelNumber = messageData[0]; - messageId = messageData[1]; - messageCode = messageData[2]; - } - - /** Returns the channel number */ - public byte getChannelNumber() { - return channelNumber; - } - - /** Returns the ID of the message being responded to */ - public byte getMessageId() { - return messageId; - } - - /** Returns the code for a specific response or event */ - public byte getMessageCode() { - return messageCode; - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManager.java deleted file mode 100644 index 669c8b040..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManager.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import static com.google.android.apps.mytracks.Constants.TAG; - -import com.dsi.ant.AntDefine; -import com.dsi.ant.AntMesg; -import com.dsi.ant.exception.AntInterfaceException; -import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.util.PreferencesUtils; -import com.google.android.maps.mytracks.R; - -import android.content.Context; -import android.util.Log; - -/** - * A sensor manager to connect ANT+ sensors. - * - * @author Sandor Dornbush - * @author Laszlo Molnar - */ -public class AntDirectSensorManager extends AntSensorManager - implements AntSensorDataCollector { - - // allocating one channel for each sensor type - private static final byte HEART_RATE_CHANNEL = 0; - private static final byte CADENCE_CHANNEL = 1; - private static final byte CADENCE_SPEED_CHANNEL = 2; - - // ids for device number preferences - private static final int sensorIdKeys[] = { - R.string.ant_heart_rate_sensor_id_key, - R.string.ant_cadence_sensor_id_key, - R.string.ant_cadence_speed_sensor_id_key, - }; - - private AntSensorBase sensors[] = null; - - // current data to be sent for SensorDataSet - private static final byte HEART_RATE_DATA_INDEX = 0; - private static final byte CADENCE_DATA_INDEX = 1; - private int currentSensorData[] = { -1, -1 }; - - private long lastDataSentMillis = 0; - private byte connectingChannelsBitmap = 0; - - public AntDirectSensorManager(Context context) { - super(context); - } - - @Override - protected boolean handleMessage(byte messageId, byte[] messageData) { - if (super.handleMessage(messageId, messageData)) { - return true; - } - - int channel = messageData[0] & AntDefine.CHANNEL_NUMBER_MASK; - if (sensors == null || channel >= sensors.length) { - Log.d(TAG, "Unknown channel in message: " + channel); - return false; - } - - AntSensorBase sensor = sensors[channel]; - switch (messageId) { - case AntMesg.MESG_BROADCAST_DATA_ID: - if (sensor.getDeviceNumber() == WILDCARD) { - resolveWildcardDeviceNumber((byte) channel); - } - sensor.handleBroadcastData(messageData, this); - break; - case AntMesg.MESG_RESPONSE_EVENT_ID: - handleMessageResponse(messageData); - break; - case AntMesg.MESG_CHANNEL_ID_ID: - sensor.setDeviceNumber(handleChannelId(messageData)); - break; - default: - Log.e(TAG, "Unexpected ANT message id: " + messageId); - } - - return true; - } - - private short handleChannelId(byte[] rawMessage) { - AntChannelIdMessage message = new AntChannelIdMessage(rawMessage); - short deviceNumber = message.getDeviceNumber(); - byte channel = message.getChannelNumber(); - if (channel >= sensors.length) { - Log.d(TAG, "Unknown channel in message: " + channel); - return WILDCARD; - } - Log.i(TAG, "Found ANT device id: " + deviceNumber + " on channel: " + channel); - - PreferencesUtils.setInt(context, sensorIdKeys[channel], deviceNumber); - return deviceNumber; - } - - private void channelOut(byte channel) - { - if (channel >= sensors.length) { - Log.d(TAG, "Unknown channel in message: " + channel); - return; - } - connectingChannelsBitmap &= ~(1 << channel); - Log.i(TAG, "ANT channel " + channel + " disconnected."); - - if (sensors[channel].getDeviceNumber() != WILDCARD) { - Log.i(TAG, "Retrying...."); - if (setupChannel(sensors[channel], channel)) { - connectingChannelsBitmap |= 1 << channel; - } - } - if (connectingChannelsBitmap == 0) { - setSensorState(Sensor.SensorState.DISCONNECTED); - } - } - - private void handleMessageResponse(byte[] rawMessage) { - AntChannelResponseMessage message = new AntChannelResponseMessage(rawMessage); - byte channel = message.getChannelNumber(); - switch (message.getMessageId()) { - case AntMesg.MESG_EVENT_ID: - if (message.getMessageCode() == AntDefine.EVENT_RX_SEARCH_TIMEOUT) { - // Search timeout - Log.w(TAG, "ANT search timed out. Unassigning channel " + channel); - try { - getAntReceiver().ANTUnassignChannel(channel); - } catch (AntInterfaceException e) { - Log.e(TAG, "ANT error unassigning channel", e); - channelOut(channel); - } - } - break; - - case AntMesg.MESG_UNASSIGN_CHANNEL_ID: - channelOut(channel); - break; - } - } - - private void resolveWildcardDeviceNumber(byte channel) { - try { - getAntReceiver().ANTRequestMessage(channel, AntMesg.MESG_CHANNEL_ID_ID); - } catch (AntInterfaceException e) { - Log.e(TAG, "ANT error handling broadcast data", e); - } - Log.d(TAG, "Requesting channel id id on channel: " + channel); - } - - @Override - protected void setupAntSensorChannels() { - short devIds[] = new short[sensorIdKeys.length]; - - for (int i = 0; i < sensorIdKeys.length; ++i) { - devIds[i] = (short) PreferencesUtils.getInt(context, sensorIdKeys[i], WILDCARD); - } - - sensors = new AntSensorBase[] { - new HeartRateSensor(devIds[HEART_RATE_CHANNEL]), - new CadenceSensor(devIds[CADENCE_CHANNEL]), - new CadenceSpeedSensor(devIds[CADENCE_SPEED_CHANNEL]), - }; - - connectingChannelsBitmap = 0; - for (int i = 0; i < sensors.length; ++i) { - if (setupChannel(sensors[i], (byte) i)) { - connectingChannelsBitmap |= 1 << i; - } - } - if (connectingChannelsBitmap == 0) { - setSensorState(Sensor.SensorState.DISCONNECTED); - } - } - - protected boolean setupChannel(AntSensorBase sensor, byte channel) { - Log.i(TAG, "setup channel=" + channel + " deviceType=" + sensor.getDeviceType()); - - return setupAntSensorChannel(sensor.getNetworkNumber(), - channel, - sensor.getDeviceNumber(), - sensor.getDeviceType(), - (byte) 0x01, - sensor.getChannelPeriod(), - sensor.getFrequency(), - (byte) 0); - } - - private void sendSensorData(byte index, int value) { - if (index >= currentSensorData.length) { - Log.w(TAG, "invalid index in sendSensorData:" + index); - return; - } - currentSensorData[index] = value; - - long now = System.currentTimeMillis(); - // data comes in at ~4Hz rate from the sensors, so after >300 msec - // fresh data is here from all the connected sensors - if (now < lastDataSentMillis + 300) { - return; - } - lastDataSentMillis = now; - setSensorState(Sensor.SensorState.CONNECTED); - - Sensor.SensorDataSet.Builder b = Sensor.SensorDataSet.newBuilder(); - if (currentSensorData[HEART_RATE_DATA_INDEX] >= 0) { - b.setHeartRate( - Sensor.SensorData.newBuilder() - .setValue(currentSensorData[HEART_RATE_DATA_INDEX]) - .setState(Sensor.SensorState.SENDING)); - } - - if (currentSensorData[CADENCE_DATA_INDEX] >= 0) { - b.setCadence( - Sensor.SensorData.newBuilder() - .setValue(currentSensorData[CADENCE_DATA_INDEX]) - .setState(Sensor.SensorState.SENDING)); - } - sensorData = b.setCreationTime(now).build(); - } - - public void setCadence(int value) { - sendSensorData(CADENCE_DATA_INDEX, value); - } - - public void setHeartRate(int value) { - sendSensorData(HEART_RATE_DATA_INDEX, value); - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntMessage.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntMessage.java deleted file mode 100644 index b11c76da9..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntMessage.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -/** - * This is a common superclass for ANT message subclasses. - * - * @author Matthew Simmons - */ -public class AntMessage { - protected AntMessage() {} - - /** Build a short value from its constituent bytes */ - protected static short decodeShort(byte b0, byte b1) { - int value = b0 & 0xFF; - value |= (b1 & 0xFF) << 8; - return (short)value; - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensor.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensor.java deleted file mode 100644 index beac735a5..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.google.android.apps.mytracks.services.sensors.ant; - -/** - * A enum which stores static data about ANT sensors. - * - * @author Matthew Simmons - */ -public enum AntSensor { - SENSOR_HEART_RATE (Constants.ANT_DEVICE_TYPE_HRM), - SENSOR_CADENCE (Constants.ANT_DEVICE_TYPE_CADENCE), - SENSOR_SPEED (Constants.ANT_DEVICE_TYPE_SPEED), - SENSOR_POWER (Constants.ANT_DEVICE_TYPE_POWER); - - private static class Constants { - public static byte ANT_DEVICE_TYPE_POWER = 11; - public static byte ANT_DEVICE_TYPE_HRM = 120; - public static byte ANT_DEVICE_TYPE_CADENCE = 122; - public static byte ANT_DEVICE_TYPE_SPEED = 123; - }; - - private final byte deviceType; - - private AntSensor(byte deviceType) { - this.deviceType = deviceType; - } - - public byte getDeviceType() { - return deviceType; - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorBase.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorBase.java deleted file mode 100644 index 6e2dfb3f1..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorBase.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import static com.google.android.apps.mytracks.Constants.TAG; - -import android.util.Log; - -/** - * Base class for ANT+ sensors. - * - * @author Laszlo Molnar - */ - -public abstract class AntSensorBase { - /* - * These constants are defined by the ANT+ spec. - */ - public static final byte NETWORK_NUMBER = 1; - public static final byte RF_FREQUENCY = 57; - - private short deviceNumber; - private final byte deviceType; - private final short channelPeriod; - - AntSensorBase(short deviceNumber, byte deviceType, - String deviceTypeString, short channelPeriod) { - this.deviceNumber = deviceNumber; - this.deviceType = deviceType; - this.channelPeriod = channelPeriod; - - Log.i(TAG, "Will pair with " + deviceTypeString + " device: " + ((int) deviceNumber & 0xFFFF)); - } - - public abstract void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c); - - public void setDeviceNumber(short dn) { - deviceNumber = dn; - } - - public short getDeviceNumber() { - return deviceNumber; - } - - public byte getNetworkNumber() { - return NETWORK_NUMBER; - } - - public byte getFrequency() { - return RF_FREQUENCY; - } - - public byte getDeviceType() { - return deviceType; - } - - public short getChannelPeriod() { - return channelPeriod; - } -}; diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorManager.java index d174a6138..2ed9f6cf1 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorManager.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2009 Google Inc. + * Copyright 2012 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of @@ -13,9 +13,8 @@ * License for the specific language governing permissions and limitations under * the License. */ -package com.google.android.apps.mytracks.services.sensors.ant; -import static com.google.android.apps.mytracks.Constants.TAG; +package com.google.android.apps.mytracks.services.sensors.ant; import com.dsi.ant.AntDefine; import com.dsi.ant.AntInterface; @@ -25,361 +24,696 @@ import com.dsi.ant.exception.AntInterfaceException; import com.dsi.ant.exception.AntServiceNotConnectedException; import com.google.android.apps.mytracks.content.Sensor; import com.google.android.apps.mytracks.content.Sensor.SensorDataSet; +import com.google.android.apps.mytracks.content.Sensor.SensorState; import com.google.android.apps.mytracks.services.sensors.SensorManager; +import com.google.android.apps.mytracks.util.PreferencesUtils; +import com.google.android.maps.mytracks.R; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.provider.Settings; import android.util.Log; +import android.widget.Toast; -import java.util.Locale; +import java.lang.reflect.Field; /** - * This is the common superclass for ANT-based sensors. It handles tasks which - * apply to the ANT framework as a whole, such as framework initialization and - * destruction. Subclasses are expected to handle the initialization and - * management of individual sensors. - * - * Implementation: - * - * The initialization process is somewhat complicated. This is due in part to - * the asynchronous nature of ANT Radio Service initialization, and in part due - * to an apparent bug in that service. The following is an overview of the - * initialization process. - * - * Initialization begins in {@link #setupChannel}, which is invoked by the - * {@link SensorManager} when track recording begins. {@link #setupChannel} - * asks the ANT Radio Service (via {@link AntInterface}) to start, using a - * AntInterface.ServiceListener to indicate when the service has - * connected. {@link #serviceConnected} claims and enables the Radio Service, - * and then resets it to a known state for our use. Completion of reset is - * indicated by receipt of a startup message (see {@link AntStartupMessage}). - * Once we've received that message, the ANT service is ready for use, and we - * can start sensor-specific initialization using - * {@link #setupAntSensorChannels}. The initialization of each sensor will - * usually result in a call to {@link #setupAntSensorChannel}. - * - * @author Sandor Dornbush + * Ant Sensor Manager. + * + * @author Jimmy Shih */ -public abstract class AntSensorManager extends SensorManager { - - // Pairing - protected static final short WILDCARD = 0; - - private AntInterface antReceiver; +public class AntSensorManager extends SensorManager { /** - * The data from the sensors. + * Channel States */ - protected SensorDataSet sensorData; + public enum ChannelStates { + CLOSED, // Channel is closed + PENDING_OPEN, // User has requested opening the channel, waiting for a reset + SEARCHING, // Channel is opened, but has not received data + TRACKING_STATUS, // Channel is opened and has received status data recently + TRACKING_DATA, // Channel is opened and has received measurement data + // recently + OFFLINE // Channel is closed as the result of a search timeout + } - protected Context context; + private static final String TAG = AntSensorManager.class.getSimpleName(); - private static final boolean DEBUGGING = false; + public static final short WILDCARD = 0; - /** Receives and logs all status ANT intents. */ - private final BroadcastReceiver statusReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context ctx, Intent intent) { - String antAction = intent.getAction(); - Log.i(TAG, "enter status onReceive" + antAction); - } - }; + private static final int CHANNELS = 2; + private static final byte HRM_CHANNEL = (byte) 0; + private static final byte SDM_CHANNEL = (byte) 1; - /** Receives all data ANT intents. */ - private final BroadcastReceiver dataReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context ctx, Intent intent) { - String antAction = intent.getAction(); - Log.i(TAG, "enter data onReceive" + antAction); + private static final byte HRM_DEVICE_TYPE = 0x78; + private static final byte SDM_DEVICE_TYPE = 0x7C; - if (antAction != null && antAction.equals(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION)) { - byte[] antMessage = intent.getByteArrayExtra(AntInterfaceIntent.ANT_MESSAGE); - if (DEBUGGING) { - Log.d(TAG, "Received RX message " + messageToString(antMessage)); - } - if (getAntReceiver() != null) { - handleMessage(antMessage); + private static final short HRM_PERIOD = 8070; + private static final short SDM_PERIOD = 8134; + + private static final byte DEFAULT_PROXIMITY_SEARCH_BIN = 7; + private static final short SCREEN_ON_BUFFER_THRESHOLD = AntDefine.MIN_BUFFER_THRESHOLD; + private static final short SCREEN_OFF_BUFFER_THRESHOLD = AntDefine.MAX_BUFFER_THRESHOLD; + + private static final String RADIO_ANT = "ant"; + private static final byte ANT_NETWORK = (byte) 0x01; + private static final int ANT_FREQUENCY = 57; // 2457Mhz (Ant+ frequency) + private static final int ANT_TRANSMISSION_TYPE = 0; // 0 for wild card search + + private final Context context; + private final ChannelConfiguration channelConfig[]; + private final IntentFilter statusIntentFilter; + private final AntInterface antInterface; + + private boolean serviceConnected = false; + private boolean hasClaimedInterface = false; + private ChannelStates hrmState = ChannelStates.CLOSED; + private ChannelStates sdmState = ChannelStates.CLOSED; + private short hrmDeviceNumber = WILDCARD; + private short sdmDeviceNumber = WILDCARD; + + private SensorDataSet sensorDataSet = null; + private int lastHeartRate = -1; + private int lastCadence = -1; + private long lastSensorDataSetTime = 0; + + private boolean requestedReset = false; + + /** + * Constructor. + * + * @param context the context + */ + public AntSensorManager(Context context) { + this.context = context; + + channelConfig = new ChannelConfiguration[CHANNELS]; + channelConfig[HRM_CHANNEL] = new ChannelConfiguration(); + channelConfig[SDM_CHANNEL] = new ChannelConfiguration(); + + statusIntentFilter = new IntentFilter(); + statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLED_ACTION); + statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLING_ACTION); + statusIntentFilter.addAction(AntInterfaceIntent.ANT_DISABLED_ACTION); + statusIntentFilter.addAction(AntInterfaceIntent.ANT_DISABLING_ACTION); + statusIntentFilter.addAction(AntInterfaceIntent.ANT_RESET_ACTION); + statusIntentFilter.addAction(AntInterfaceIntent.ANT_INTERFACE_CLAIMED_ACTION); + statusIntentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); + + antInterface = new AntInterface(); + } + + @Override + protected void setUpChannel() { + if (AntInterface.hasAntSupport(context)) { + context.registerReceiver(statusReceiver, statusIntentFilter); + if (!antInterface.initService(context, serviceListener)) { + AntInterface.goToMarket(context); + } else { + setSensorState(Sensor.SensorState.CONNECTING); + serviceConnected = antInterface.isServiceConnected(); + if (serviceConnected) { + try { + hasClaimedInterface = antInterface.hasClaimedInterface(); + if (hasClaimedInterface) { + enableDataMessage(true); + } + } catch (AntInterfaceException e) { + handleAntError(); + } } } } - }; - - /** - * ANT uses this listener to tell us when it has bound to the ANT Radio - * Service. We can't start sending ANT commands until we've been notified - * (via this listener) that the Radio Service has connected. - */ - private AntInterface.ServiceListener antServiceListener = new AntInterface.ServiceListener() { - @Override - public void onServiceConnected() { - serviceConnected(); - } - - @Override - public void onServiceDisconnected() { - Log.d(TAG, "ANT interface reports disconnection"); - } - }; - - public AntSensorManager(Context context) { - this.context = context; - - // We register for ANT intents early because we want to have a record of - // the status intents in the log as we start up. - registerForAntIntents(); - } @Override protected void tearDownChannel() { - Log.i(TAG, "destroying AntSensorManager"); - - cleanAntInterface(); - unregisterForAntIntents(); + try { + context.unregisterReceiver(statusReceiver); + } catch (IllegalArgumentException e) { + // Can safely ignore + } + enableDataMessage(false); + if (serviceConnected) { + try { + if (hasClaimedInterface) { + antInterface.releaseInterface(); + } + antInterface.stopRequestForceClaimInterface(); + } catch (AntServiceNotConnectedException e) { + // Can safely ignore + } catch (AntInterfaceException e) { + Log.w(TAG, "Exception in tearDonwChannel.", e); + } + antInterface.releaseService(); + } } @Override public SensorDataSet getSensorDataSet() { - return sensorData; + return sensorDataSet; + } + + /** + * Tries to claim the ant interface. + */ + public void tryClaimAnt() { + try { + antInterface.requestForceClaimInterface(context.getString(R.string.my_tracks_app_name)); + } catch (AntInterfaceException e) { + handleAntError(); + } + } + + private AntInterface.ServiceListener serviceListener = new AntInterface.ServiceListener() { + @Override + public void onServiceConnected() { + serviceConnected = true; + try { + hasClaimedInterface = antInterface.hasClaimedInterface(); + if (hasClaimedInterface) { + enableDataMessage(true); + } else { + // Need to claim the ant interface if it is available + hasClaimedInterface = antInterface.claimInterface(); + } + } catch (AntInterfaceException e) { + handleAntError(); + } + } + + @Override + public void onServiceDisconnected() { + serviceConnected = false; + if (hasClaimedInterface) { + enableDataMessage(false); + } + } + }; + + /** + * Configures ant radio. + */ + private void configureAntRadio() { + try { + if (serviceConnected && hasClaimedInterface && antInterface.isEnabled()) { + try { + antInterface.ANTConfigEventBuffering((short) 0xFFFF, SCREEN_ON_BUFFER_THRESHOLD, + (short) 0xFFFF, SCREEN_OFF_BUFFER_THRESHOLD); + } catch (AntInterfaceException e) { + Log.e(TAG, "Cannot configure event buffering.", e); + } + } else { + Log.i(TAG, "Cannot set event buffering now."); + } + } catch (AntInterfaceException e) { + Log.e(TAG, "Unable to check enabled state.", e); + } + } + + /** + * Handles ant error. + */ + private void handleAntError() { + clearAllChannels(); + } + + /** + * Opens a channel. + * + * @param channel the channel + */ + private void openChannel(byte channel) { + channelConfig[channel].deviceNumber = 0; + channelConfig[channel].deviceType = 0; + channelConfig[channel].TransmissionType = ANT_TRANSMISSION_TYPE; + channelConfig[channel].period = 0; + channelConfig[channel].freq = ANT_FREQUENCY; + channelConfig[channel].proxSearch = DEFAULT_PROXIMITY_SEARCH_BIN; + switch (channel) { + case HRM_CHANNEL: + hrmDeviceNumber = (short) PreferencesUtils.getInt( + context, R.string.ant_heart_rate_monitor_id_key, WILDCARD); + channelConfig[channel].deviceNumber = hrmDeviceNumber; + channelConfig[channel].deviceType = HRM_DEVICE_TYPE; + channelConfig[channel].period = HRM_PERIOD; + hrmState = ChannelStates.PENDING_OPEN; + break; + case SDM_CHANNEL: + sdmDeviceNumber = (short) PreferencesUtils.getInt( + context, R.string.ant_speed_distance_monitor_id_key, WILDCARD); + channelConfig[channel].deviceNumber = sdmDeviceNumber; + channelConfig[channel].deviceType = SDM_DEVICE_TYPE; + channelConfig[channel].period = SDM_PERIOD; + sdmState = ChannelStates.PENDING_OPEN; + break; + default: + break; + } + setupAntChannel(ANT_NETWORK, channel); + } + + /** + * Closes a channel. + * + * @param channel the channel + */ + private void closeChannel(byte channel) { + channelConfig[channel].isInitializing = false; + channelConfig[channel].isDeinitializing = true; + switch (channel) { + case HRM_CHANNEL: + hrmState = ChannelStates.CLOSED; + break; + case SDM_CHANNEL: + sdmState = ChannelStates.CLOSED; + break; + default: + break; + } + setSensorState(SensorState.DISCONNECTED); + try { + antInterface.ANTCloseChannel(channel); + // Note, unassign channel after getting channel closed event + } catch (AntInterfaceException e) { + Log.w(TAG, "Unable to close channel: " + channel, e); + handleAntError(); + } + } + + /** + * Clears all channels. + */ + private void clearAllChannels() { + hrmState = ChannelStates.CLOSED; + sdmState = ChannelStates.CLOSED; + setSensorState(SensorState.DISCONNECTED); + } + + /** + * Requests reset. + */ + public void requestReset() { + try { + requestedReset = true; + antInterface.ANTResetSystem(); + configureAntRadio(); + } catch (AntInterfaceException e) { + Log.e(TAG, "Unable to reset ant.", e); + requestedReset = false; + } } @Override public boolean isEnabled() { - return true; - } - - public AntInterface getAntReceiver() { - return antReceiver; - } - - /** - * This is the interface used by the {@link SensorManager} to tell this - * class when to start. It handles initialization of the ANT framework, - * eventually resulting in sensor-specific initialization via - * {@link #setupAntSensorChannels}. - */ - @Override - protected void setUpChannel() { - setup(); - } - - private synchronized void setup() { - // We handle this unpleasantly because the UI should've checked for ANT - // support before it even instantiated this class. - if (!AntInterface.hasAntSupport(context)) { - throw new IllegalStateException("device does not have ANT support"); + if (antInterface == null || !antInterface.isServiceConnected()) { + return false; } - - cleanAntInterface(); - - antReceiver = AntInterface.getInstance(context, antServiceListener); - - if (antReceiver == null) { - Log.e(TAG, "Failed to get ANT Receiver"); - return; - } - - setSensorState(Sensor.SensorState.CONNECTING); - } - - /** - * Cleans up the ANT+ receiver interface, by releasing the interface - * and destroying it. - */ - private void cleanAntInterface() { - Log.i(TAG, "Destroying AntSensorManager"); - - if (antReceiver == null) { - Log.e(TAG, "no ANT receiver"); - return; - } - try { - antReceiver.releaseInterface(); - antReceiver.destroy(); - antReceiver = null; - } catch (AntServiceNotConnectedException e) { - Log.i(TAG, "ANT service not connected", e); + return antInterface.isEnabled(); } catch (AntInterfaceException e) { - Log.e(TAG, "failed to release ANT interface", e); - } catch (RuntimeException e) { - Log.e(TAG, "run-time exception when cleaning the ANT interface", e); - } - } - - /** - * This method is invoked via the ServiceListener when we're connected to - * the ANT service. If we're just starting up, this is our first opportunity - * to initiate any ANT commands. - */ - private synchronized void serviceConnected() { - Log.d(TAG, "ANT service connected"); - - if (antReceiver == null) { - Log.e(TAG, "no ANT receiver"); - return; - } - - try { - if (!antReceiver.claimInterface()) { - Log.e(TAG, "failed to claim ANT interface"); - return; - } - - if (!antReceiver.isEnabled()) { - // Make sure not to call AntInterface.enable() again, if it has been - // already called before - Log.i(TAG, "Powering on Radio"); - antReceiver.enable(); - } else { - Log.i(TAG, "Radio already enabled"); - } - } catch (AntInterfaceException e) { - Log.e(TAG, "failed to enable ANT", e); - } - - try { - // We expect this call to throw an exception due to a bug in the ANT - // Radio Service. It won't actually fail, though, as we'll get the - // startup message (see {@link AntStartupMessage}) one normally expects - // after a reset. Channel initialization can proceed once we receive - // that message. - antReceiver.ANTResetSystem(); - } catch (AntInterfaceException e) { - Log.e(TAG, "failed to reset ANT (expected exception)", e); - } - } - - /** - * Process a raw ANT message. - * @param antMessage the ANT message, including the size and message ID bytes - * @deprecated Use {@link #handleMessage(byte, byte[])} instead. - */ - protected void handleMessage(byte[] antMessage) { - int len = antMessage[0]; - if (len != antMessage.length - 2 || antMessage.length <= 2) { - Log.e(TAG, "Invalid message: " + messageToString(antMessage)); - return; - } - - byte messageId = antMessage[1]; - // Arrays#copyOfRange doesn't exist?? - byte[] messageData = new byte[antMessage.length - 2]; - System.arraycopy(antMessage, 2, messageData, 0, antMessage.length - 2); - handleMessage(messageId, messageData); - } - - /** - * Process a raw ANT message. - * @param messageId the message ID. See the ANT Message Protocol and Usage - * guide, section 9.3. - * @param messageData the ANT message, without the size and message ID bytes. - * @return true if this method has taken responsibility for the passed - * message; false otherwise. - */ - protected boolean handleMessage(byte messageId, byte[] messageData) { - if (messageId == AntMesg.MESG_STARTUP_MESG_ID) { - Log.d(TAG, String.format(Locale.US, - "Received startup message (reason %02x); initializing channel", - new AntStartupMessage(messageData).getMessage())); - setupAntSensorChannels(); - return true; - } - - return false; - } - - /** - * Subclasses define this method to perform sensor-specific initialization. - * When this method is called, the ANT framework has been enabled, and is - * ready for use. - */ - protected abstract void setupAntSensorChannels(); - - /** - * Used by subclasses to set up an ANT channel for a single sensor. A given - * subclass may invoke this method multiple times if the subclass is - * responsible for more than one sensor. - * - * @return true on success - */ - protected boolean setupAntSensorChannel(byte networkNumber, byte channelNumber, - short deviceNumber, byte deviceType, byte txType, short channelPeriod, - byte radioFreq, byte proxSearch) { - - if (antReceiver == null) { - Log.e(TAG, "no ANT receiver"); - return false; - } - - try { - // Assign as slave channel on selected network (0 = public, 1 = ANT+, 2 = - // ANTFS) - antReceiver.ANTAssignChannel(channelNumber, AntDefine.PARAMETER_RX_NOT_TX, networkNumber); - - antReceiver.ANTSetChannelId(channelNumber, deviceNumber, deviceType, txType); - antReceiver.ANTSetChannelPeriod(channelNumber, channelPeriod); - antReceiver.ANTSetChannelRFFreq(channelNumber, radioFreq); - - // Disable high priority search - antReceiver.ANTSetChannelSearchTimeout(channelNumber, (byte) 0); - - // Set search timeout to 10 seconds (low priority search)) - antReceiver.ANTSetLowPriorityChannelSearchTimeout(channelNumber, (byte) 4); - - if (deviceNumber == WILDCARD) { - // Configure proximity search, if using wild card search - antReceiver.ANTSetProximitySearch(channelNumber, proxSearch); - } - - antReceiver.ANTOpenChannel(channelNumber); - return true; - - } catch (AntInterfaceException e) { - Log.e(TAG, "failed to setup ANT channel", e); + Log.w(TAG, "Unable to check enabled.", e); return false; } } - private void registerForAntIntents() { - Log.i(TAG, "Registering for ant intents."); - // Register for ANT intent broadcasts. - IntentFilter statusIntentFilter = new IntentFilter(); - statusIntentFilter.addAction(AntInterfaceIntent.ANT_ENABLED_ACTION); - statusIntentFilter.addAction(AntInterfaceIntent.ANT_DISABLED_ACTION); - statusIntentFilter.addAction(AntInterfaceIntent.ANT_INTERFACE_CLAIMED_ACTION); - statusIntentFilter.addAction(AntInterfaceIntent.ANT_RESET_ACTION); - context.registerReceiver(statusReceiver, statusIntentFilter); + private final BroadcastReceiver statusReceiver = new BroadcastReceiver() { + public void onReceive(Context c, Intent intent) { + String ANTAction = intent.getAction(); + if (ANTAction.equals(AntInterfaceIntent.ANT_DISABLED_ACTION)) { + clearAllChannels(); + } else if (ANTAction.equals(AntInterfaceIntent.ANT_RESET_ACTION)) { + if (!requestedReset) { + // Someone else triggered an ant reset + clearAllChannels(); + } else { + requestedReset = false; + configureAntRadio(); + } + } else if (ANTAction.equals(AntInterfaceIntent.ANT_INTERFACE_CLAIMED_ACTION)) { + boolean wasClaimed = hasClaimedInterface; - IntentFilter dataIntentFilter = new IntentFilter(); - dataIntentFilter.addAction(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION); - context.registerReceiver(dataReceiver, dataIntentFilter); + // Could also read ANT_INTERFACE_CLAIMED_PID from intent and see if it + // matches the current process PID. + try { + hasClaimedInterface = antInterface.hasClaimedInterface(); + if (hasClaimedInterface) { + enableDataMessage(true); + } else { + if (wasClaimed) { + // Claimed by another application + enableDataMessage(false); + } + } + } catch (AntInterfaceException e) { + handleAntError(); + } + } else if (ANTAction.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { + if (isAirPlaneMode()) { + clearAllChannels(); + } + } + } + }; + + private final BroadcastReceiver dataReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context c, Intent intent) { + if (intent.getAction().equals(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION)) { + byte[] ANTRxMessage = intent.getByteArrayExtra(AntInterfaceIntent.ANT_MESSAGE); + switch (ANTRxMessage[AntMesg.MESG_ID_OFFSET]) { + case AntMesg.MESG_BROADCAST_DATA_ID: + case AntMesg.MESG_ACKNOWLEDGED_DATA_ID: + // Switch on channel number + switch (ANTRxMessage[AntMesg.MESG_DATA_OFFSET]) { + case HRM_CHANNEL: + decodeHrmMessage(ANTRxMessage); + break; + case SDM_CHANNEL: + decodeSdmMessage(ANTRxMessage); + break; + default: + break; + } + break; + case AntMesg.MESG_RESPONSE_EVENT_ID: + handleResponseEventMessage(ANTRxMessage); + break; + case AntMesg.MESG_CHANNEL_ID_ID: + short deviceNum = (short) ((ANTRxMessage[AntMesg.MESG_DATA_OFFSET + 1] & 0xFF + | ((ANTRxMessage[AntMesg.MESG_DATA_OFFSET + 2] & 0xFF) << 8)) & 0xFFFF); + // Switch on channel number + switch (ANTRxMessage[AntMesg.MESG_DATA_OFFSET]) { + case HRM_CHANNEL: + hrmDeviceNumber = deviceNum; + PreferencesUtils.setInt( + context, R.string.ant_heart_rate_monitor_id_key, hrmDeviceNumber); + Toast.makeText(context, + context.getString(R.string.settings_sensor_connected, deviceNum), + Toast.LENGTH_SHORT).show(); + setSensorState(SensorState.CONNECTED); + break; + case SDM_CHANNEL: + sdmDeviceNumber = deviceNum; + PreferencesUtils.setInt( + context, R.string.ant_speed_distance_monitor_id_key, sdmDeviceNumber); + Toast.makeText(context, + context.getString(R.string.settings_sensor_connected, deviceNum), + Toast.LENGTH_SHORT).show(); + setSensorState(SensorState.CONNECTED); + break; + default: + break; + } + break; + default: + break; + } + } + } + + /** + * Handles response event message. + * + * @param message the message + */ + private void handleResponseEventMessage(byte[] message) { + // For a list of possible message codes see ANT Message Protocol and Usage + // section 9.5.6.1 available from thisisant.com + byte channelNumber = message[AntMesg.MESG_DATA_OFFSET]; + if ((message[AntMesg.MESG_DATA_OFFSET + 1] == AntMesg.MESG_EVENT_ID) + && (message[AntMesg.MESG_DATA_OFFSET + 2] == AntDefine.EVENT_RX_SEARCH_TIMEOUT)) { + // A channel timed out searching, unassign it + channelConfig[channelNumber].isInitializing = false; + channelConfig[channelNumber].isDeinitializing = false; + switch (channelNumber) { + case HRM_CHANNEL: + try { + hrmState = ChannelStates.OFFLINE; + antInterface.ANTUnassignChannel(HRM_CHANNEL); + setSensorState(SensorState.DISCONNECTED); + } catch (AntInterfaceException e) { + handleAntError(); + } + break; + case SDM_CHANNEL: + try { + sdmState = ChannelStates.OFFLINE; + antInterface.ANTUnassignChannel(SDM_CHANNEL); + setSensorState(SensorState.DISCONNECTED); + } catch (AntInterfaceException e) { + handleAntError(); + } + break; + default: + break; + } + } + + if (channelConfig[channelNumber].isInitializing) { + if (message[AntMesg.MESG_DATA_OFFSET + 2] != 0) { + // Error response + Log.e(TAG, String.format("Error code(%#02x) on message ID(%#02x) on channel %d", + message[AntMesg.MESG_DATA_OFFSET + 2], + message[AntMesg.MESG_DATA_OFFSET + 1], channelNumber)); + } else { + // Switch on message id + switch (message[AntMesg.MESG_DATA_OFFSET + 1]) { + case AntMesg.MESG_ASSIGN_CHANNEL_ID: + try { + antInterface.ANTSetChannelId(channelNumber, + channelConfig[channelNumber].deviceNumber, + channelConfig[channelNumber].deviceType, + channelConfig[channelNumber].TransmissionType); + } catch (AntInterfaceException e) { + handleAntError(); + } + break; + case AntMesg.MESG_CHANNEL_ID_ID: + try { + antInterface.ANTSetChannelPeriod( + channelNumber, channelConfig[channelNumber].period); + } catch (AntInterfaceException e) { + handleAntError(); + } + break; + case AntMesg.MESG_CHANNEL_MESG_PERIOD_ID: + try { + antInterface.ANTSetChannelRFFreq(channelNumber, channelConfig[channelNumber].freq); + } catch (AntInterfaceException e) { + handleAntError(); + } + break; + case AntMesg.MESG_CHANNEL_RADIO_FREQ_ID: + try { + // Disable high priority search + antInterface.ANTSetChannelSearchTimeout(channelNumber, (byte) 0); + } catch (AntInterfaceException e) { + handleAntError(); + } + break; + case AntMesg.MESG_CHANNEL_SEARCH_TIMEOUT_ID: + try { + // Set search timeout to 30 seconds (low priority search) + antInterface.ANTSetLowPriorityChannelSearchTimeout(channelNumber, (byte) 12); + } catch (AntInterfaceException e) { + handleAntError(); + } + break; + case AntMesg.MESG_SET_LP_SEARCH_TIMEOUT_ID: + if (channelConfig[channelNumber].deviceNumber == WILDCARD) { + try { + // Configure proximity search, if using wild card search + antInterface.ANTSetProximitySearch( + channelNumber, channelConfig[channelNumber].proxSearch); + } catch (AntInterfaceException e) { + handleAntError(); + } + } else { + try { + antInterface.ANTOpenChannel(channelNumber); + } catch (AntInterfaceException e) { + handleAntError(); + } + } + break; + case AntMesg.MESG_PROX_SEARCH_CONFIG_ID: + try { + antInterface.ANTOpenChannel(channelNumber); + } catch (AntInterfaceException e) { + handleAntError(); + } + break; + case AntMesg.MESG_OPEN_CHANNEL_ID: + channelConfig[channelNumber].isInitializing = false; + switch (channelNumber) { + case HRM_CHANNEL: + hrmState = ChannelStates.SEARCHING; + break; + case SDM_CHANNEL: + sdmState = ChannelStates.SEARCHING; + break; + default: + break; + } + break; + default: + break; + } + } + } else if (channelConfig[channelNumber].isDeinitializing) { + if ((message[AntMesg.MESG_DATA_OFFSET + 1] == AntMesg.MESG_EVENT_ID) + && (message[AntMesg.MESG_DATA_OFFSET + 2] == AntDefine.EVENT_CHANNEL_CLOSED)) { + try { + antInterface.ANTUnassignChannel(channelNumber); + } catch (AntInterfaceException e) { + handleAntError(); + } + } else if ((message[AntMesg.MESG_DATA_OFFSET + 1] == AntMesg.MESG_UNASSIGN_CHANNEL_ID) + && (message[AntMesg.MESG_DATA_OFFSET + 2] == AntDefine.RESPONSE_NO_ERROR)) { + channelConfig[channelNumber].isDeinitializing = false; + } + } + } + + /** + * Decodes HRM message. + * + * @param message the message + */ + private void decodeHrmMessage(byte[] message) { + if (hrmState != ChannelStates.CLOSED) { + hrmState = ChannelStates.TRACKING_DATA; + } + + if (hrmDeviceNumber == WILDCARD) { + try { + antInterface.ANTRequestMessage(HRM_CHANNEL, AntMesg.MESG_CHANNEL_ID_ID); + } catch (AntInterfaceException e) { + handleAntError(); + } + } + + lastHeartRate = message[10] & 0xFF; + setSenorDataSet(); + } + + /** + * Decodes SDM message. + * + * @param message the message + */ + private void decodeSdmMessage(byte[] message) { + if (sdmState != ChannelStates.CLOSED) { + sdmState = ChannelStates.TRACKING_DATA; + } + + if (sdmDeviceNumber == WILDCARD) { + try { + antInterface.ANTRequestMessage(SDM_CHANNEL, AntMesg.MESG_CHANNEL_ID_ID); + } catch (AntInterfaceException e) { + handleAntError(); + } + } + + // Check page 2 data + if (message[3] == 0x02) { + lastCadence = (int) ((message[6] & 0xFF) + (((message[7] >>> 4) & 0x0F) / 16.0f)); + setSenorDataSet(); + } + } + }; + + /** + * Sets sensor data set. + */ + private void setSenorDataSet() { + long now = System.currentTimeMillis(); + // Data comes in at ~4Hz rate from the sensors, so after >300 msec fresh + // data is here from all the connected sensors + if (now < lastSensorDataSetTime + 300) { return; } + lastSensorDataSetTime = now; + + SensorDataSet.Builder builder = Sensor.SensorDataSet.newBuilder(); + if (lastHeartRate != -1) { + builder.setHeartRate(Sensor.SensorData.newBuilder() + .setValue(lastHeartRate).setState(Sensor.SensorState.SENDING)); + } + if (lastCadence != -1) { + builder.setCadence(Sensor.SensorData.newBuilder() + .setValue(lastCadence).setState(Sensor.SensorState.SENDING)); + } + sensorDataSet = builder.setCreationTime(now).build(); + setSensorState(SensorState.SENDING); } - - private void unregisterForAntIntents() - { - Log.i(TAG, "Unregistering ANT Intents."); - + + /** + * Sets up ant channel. + * + * @param networkNumber the network number + * @param channel the channel + */ + private void setupAntChannel(byte networkNumber, byte channel) { try { - context.unregisterReceiver(statusReceiver); - } catch (IllegalArgumentException e) { - Log.w(TAG, "Failed to unregister ANT status receiver", e); + channelConfig[channel].isInitializing = true; + channelConfig[channel].isDeinitializing = false; + + // Assign as slave channel on selected network + antInterface.ANTAssignChannel(channel, AntDefine.PARAMETER_RX_NOT_TX, networkNumber); + + // The rest of the channel configuration will occur after the response is + // received in handleResponseEventMessage + } catch (AntInterfaceException aie) { + handleAntError(); + } + } + + /** + * Enables data message. + * + * @param enabled true to enable + */ + private void enableDataMessage(boolean enabled) { + if (enabled) { + context.registerReceiver( + dataReceiver, new IntentFilter(AntInterfaceIntent.ANT_RX_MESSAGE_ACTION)); + openChannel(HRM_CHANNEL); + openChannel(SDM_CHANNEL); + } else { + try { + context.unregisterReceiver(dataReceiver); + closeChannel(HRM_CHANNEL); + closeChannel(SDM_CHANNEL); + setSensorState(SensorState.DISCONNECTED); + } catch (IllegalArgumentException e) { + // Can safely ignore + } + } + } + + /** + * Returns true if in airplane mode. + */ + private boolean isAirPlaneMode() { + if (!Settings.System.getString( + context.getContentResolver(), Settings.System.AIRPLANE_MODE_RADIOS) + .contains(RADIO_ANT)) { + return false; + } + if (Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) + == 0) { + return false; } try { - context.unregisterReceiver(dataReceiver); - } catch (IllegalArgumentException e) { - Log.w(TAG, "Failed to unregister ANT data receiver", e); + Field field = Settings.System.class.getField("AIRPLANE_MODE_TOGGLEABLE_RADIOS"); + return !Settings.System.getString(context.getContentResolver(), (String) field.get(null)) + .contains(RADIO_ANT); + } catch (Exception e) { + // This is expected if the list does not yet exist, so just return true + return true; } - } - - private String messageToString(byte[] message) { - StringBuilder out = new StringBuilder(); - for (byte b : message) { - out.append(String.format(Locale.US, "%s%02x", (out.length() == 0 ? "" : " "), b)); - } - return out.toString(); } } diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSrmBridgeSensorManager.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSrmBridgeSensorManager.java deleted file mode 100644 index be6c172ec..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSrmBridgeSensorManager.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import static com.google.android.apps.mytracks.Constants.TAG; - -import com.dsi.ant.AntDefine; -import com.dsi.ant.AntMesg; -import com.dsi.ant.exception.AntInterfaceException; -import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.util.PreferencesUtils; -import com.google.android.maps.mytracks.BuildConfig; -import com.google.android.maps.mytracks.R; - -import android.content.Context; -import android.util.Log; - -/** - * A sensor manager to the PC7 SRM ANT+ bridge. - * - * @author Sandor Dornbush - * @author Umran Abdulla - */ -public class AntSrmBridgeSensorManager extends AntSensorManager { - - /* - * These constants are defined by the ANT+ spec. - */ - public static final byte CHANNEL_NUMBER = 0; - public static final byte NETWORK_NUMBER = 0; - public static final byte DEVICE_TYPE = 12; - public static final byte NETWORK_ID = 1; - public static final short CHANNEL_PERIOD = 8192; - public static final byte RF_FREQUENCY = 50; - - private static final int INDEX_MESSAGE_TYPE = 1; - private static final int INDEX_MESSAGE_ID = 2; - private static final int INDEX_MESSAGE_POWER = 3; - private static final int INDEX_MESSAGE_SPEED = 5; - private static final int INDEX_MESSAGE_CADENCE = 7; - private static final int INDEX_MESSAGE_BPM = 8; - - private static final int MSG_INITIAL = 5; - private static final int MSG_DATA = 6; - - private short deviceNumber; - - public AntSrmBridgeSensorManager(Context context) { - super(context); - - Log.i(TAG, "new ANT SRM Bridge Sensor Manager created"); - - deviceNumber = WILDCARD; - - // First read the the device id that we will be pairing with. - deviceNumber = (short) PreferencesUtils.getInt( - context, R.string.ant_srm_bridge_sensor_id_key, WILDCARD); - Log.i(TAG, "Will pair with device: " + deviceNumber); - } - - - @Override - protected boolean handleMessage(byte messageId, byte[] messageData) { - if (super.handleMessage(messageId, messageData)) { - return true; - } - - if (BuildConfig.DEBUG) { - Log.d(TAG, "Received ANT msg: " + AntUtils.antMessageToString(messageId) + "(" + messageId + ")"); - } - - int channel = messageData[0] & AntDefine.CHANNEL_NUMBER_MASK; - switch (channel) { - case CHANNEL_NUMBER: - decodeChannelMsg(messageId, messageData); - break; - default: - Log.d(TAG, "Unhandled message: " + channel); - } - - return true; - } - - /** - * Decode an ant device message. - * @param messageData The byte array received from the device. - */ - private void decodeChannelMsg(int messageId, byte[] messageData) { - switch (messageId) { - case AntMesg.MESG_BROADCAST_DATA_ID: - handleBroadcastData(messageData); - break; - case AntMesg.MESG_RESPONSE_EVENT_ID: - handleMessageResponse(messageData); - break; - case AntMesg.MESG_CHANNEL_ID_ID: - handleChannelId(messageData); - break; - default: - Log.e(TAG, "Unexpected message id: " + messageId); - } - } - - private void handleBroadcastData(byte[] antMessage) { - if (deviceNumber == WILDCARD) { - try { - getAntReceiver().ANTRequestMessage(CHANNEL_NUMBER, AntMesg.MESG_CHANNEL_ID_ID); - } catch (AntInterfaceException e) { - Log.e(TAG, "ANT error handling broadcast data", e); - } - Log.d(TAG, "Requesting channel id id."); - } - - setSensorState(Sensor.SensorState.CONNECTED); - - int messageType = antMessage[INDEX_MESSAGE_TYPE] & 0xFF; - Log.d(TAG, "Received message-type=" + messageType); - - switch (messageType) { - case MSG_INITIAL: - break; - case MSG_DATA: - parseDataMsg(antMessage); - break; - } - } - - private void parseDataMsg(byte[] msg) - { - int messageId = msg[INDEX_MESSAGE_ID] & 0xFF; - Log.d(TAG, "Received message-id=" + messageId); - - int powerVal = (((msg[INDEX_MESSAGE_POWER] & 0xFF) << 8) | - (msg[INDEX_MESSAGE_POWER+1] & 0xFF)); - @SuppressWarnings("unused") - int speedVal = (((msg[INDEX_MESSAGE_SPEED] & 0xFF) << 8) | - (msg[INDEX_MESSAGE_SPEED+1] & 0xFF)); - int cadenceVal = (msg[INDEX_MESSAGE_CADENCE] & 0xFF); - int bpmVal = (msg[INDEX_MESSAGE_BPM] & 0xFF); - long time = System.currentTimeMillis(); - - Sensor.SensorData.Builder power = - Sensor.SensorData.newBuilder() - .setValue(powerVal) - .setState(Sensor.SensorState.SENDING); - - /* - * Although speed is available from the SRM Bridge, MyTracks doesn't use the value, and - * computes speed from the GPS location data. - */ -// Sensor.SensorData.Builder speed = Sensor.SensorData.newBuilder().setValue(speedVal).setState( -// Sensor.SensorState.SENDING); - - Sensor.SensorData.Builder cadence = - Sensor.SensorData.newBuilder() - .setValue(cadenceVal) - .setState(Sensor.SensorState.SENDING); - - Sensor.SensorData.Builder bpm = - Sensor.SensorData.newBuilder() - .setValue(bpmVal) - .setState(Sensor.SensorState.SENDING); - - sensorData = - Sensor.SensorDataSet.newBuilder() - .setCreationTime(time) - .setPower(power) - .setCadence(cadence) - .setHeartRate(bpm) - .build(); - } - - void handleChannelId(byte[] rawMessage) { - AntChannelIdMessage message = new AntChannelIdMessage(rawMessage); - deviceNumber = message.getDeviceNumber(); - Log.d(TAG, "Found device id: " + deviceNumber); - PreferencesUtils.setInt(context, R.string.ant_srm_bridge_sensor_id_key, deviceNumber); - } - - private void handleMessageResponse(byte[] rawMessage) { - AntChannelResponseMessage message = - new AntChannelResponseMessage(rawMessage); - if (BuildConfig.DEBUG) { - Log.d(TAG, "Received ANT Response: " + AntUtils.antMessageToString(message.getMessageId()) + - "(" + message.getMessageId() + ")" + - ", Code: " + AntUtils.antEventToStr(message.getMessageCode()) + - "(" + message.getMessageCode() + ")"); - } - switch (message.getMessageId()) { - case AntMesg.MESG_EVENT_ID: - if (message.getMessageCode() == AntDefine.EVENT_RX_SEARCH_TIMEOUT) { - // Search timeout - Log.w(TAG, "Search timed out. Unassigning channel."); - try { - getAntReceiver().ANTUnassignChannel((byte) 0); - } catch (AntInterfaceException e) { - Log.e(TAG, "ANT error unassigning channel", e); - } - } - break; - - case AntMesg.MESG_UNASSIGN_CHANNEL_ID: - setSensorState(Sensor.SensorState.DISCONNECTED); - Log.i(TAG, "Disconnected from the sensor: " + getSensorState()); - break; - } - } - - @Override protected void setupAntSensorChannels() { - Log.i(TAG, "Setting up ANT sensor channels"); - setupAntSensorChannel( - NETWORK_NUMBER, - CHANNEL_NUMBER, - deviceNumber, - DEVICE_TYPE, - (byte) 0x01, - CHANNEL_PERIOD, - RF_FREQUENCY, - (byte) 0); - } - - public short getDeviceNumber() { - return deviceNumber; - } - - void setDeviceNumber(short deviceNumber) { - this.deviceNumber = deviceNumber; - } -} \ No newline at end of file diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntStartupMessage.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntStartupMessage.java deleted file mode 100644 index 3e4dc1f68..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntStartupMessage.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -/** - * This class decodes and encapsulates an ANT Startup message. - * (ANT Message ID 0x6f, Protocol & Usage guide v4.2 section 9.5.3.1) - * - * @author Matthew Simmons - */ -public class AntStartupMessage extends AntMessage { - private byte message; - - public AntStartupMessage(byte[] messageData) { - message = messageData[0]; - } - - /** Returns the cause of the startup */ - public byte getMessage() { - return message; - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntUtils.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntUtils.java deleted file mode 100644 index b8019c8da..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntUtils.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import com.dsi.ant.AntDefine; -import com.dsi.ant.AntInterface; - -import android.content.Context; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.HashSet; -import java.util.Set; - -/** - * Utility methods for ANT functionality. - * - * Prefer use of this class to importing DSI ANT classes into code outside of - * the sensors package. - */ -public class AntUtils { - private AntUtils() {} - - /** Returns true if this device supports ANT sensors. */ - public static boolean hasAntSupport(Context context) { - return AntInterface.hasAntSupport(context); - } - - /** - * Finds the names of in the messages with the given value - */ - public static String antMessageToString(byte msg) { - return findConstByteInClass(AntDefine.class, msg, "MESG_.*_ID"); - } - - /** - * Finds the names of in the events with the given value - */ - public static String antEventToStr(byte event) { - return findConstByteInClass(AntDefine.class, event, ".*EVENT.*"); - } - - /** - * Finds a set of constant static byte field declarations in the class that have the given value - * and whose name match the given pattern - * @param cl class to search in - * @param value value of constant static byte field declarations to match - * @param regexPattern pattern to match against the name of the field - * @return a set of the names of fields, expressed as a string - */ - private static String findConstByteInClass(Class cl, byte value, String regexPattern) - { - Field[] fields = cl.getDeclaredFields(); - Set fieldSet = new HashSet(); - for (Field f : fields) { - try { - if (f.getType() == Byte.TYPE && - (f.getModifiers() & Modifier.STATIC) != 0 && - f.getName().matches(regexPattern) && - f.getByte(null) == value) { - fieldSet.add(f.getName()); - } - } catch (IllegalArgumentException e) { - // ignore - } catch (IllegalAccessException e) { - // ignore - } - } - return fieldSet.toString(); - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/CadenceSensor.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/CadenceSensor.java deleted file mode 100644 index 8931629f7..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/CadenceSensor.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - - -/** - * Ant+ cadence sensor. - * - * @author Laszlo Molnar - */ - -public class CadenceSensor extends AntSensorBase { - /* - * These constants are defined by the ANT+ bike speed and cadence sensor spec. - */ - public static final byte CADENCE_DEVICE_TYPE = 122; - public static final short CADENCE_CHANNEL_PERIOD = 8102; - - SensorEventCounter dataProcessor = new SensorEventCounter(); - - CadenceSensor(short devNum) { - super(devNum, CADENCE_DEVICE_TYPE, "cadence sensor", CADENCE_CHANNEL_PERIOD); - } - - /** - * Decode an ANT+ cadence sensor message. - * @param antMessage The byte array received from the cadence sensor. - */ - @Override - public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) { - int sensorTime = ((int) antMessage[5] & 0xFF) + ((int) antMessage[6] & 0xFF) * 256; - int crankRevs = ((int) antMessage[7] & 0xFF) + ((int) antMessage[8] & 0xFF) * 256; - c.setCadence(dataProcessor.getEventsPerMinute(crankRevs, sensorTime)); - } -}; diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/CadenceSpeedSensor.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/CadenceSpeedSensor.java deleted file mode 100644 index 91d83677f..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/CadenceSpeedSensor.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - - -/** - * Ant+ combined cadence and speed sensor. - * - * @author Laszlo Molnar - */ - -public class CadenceSpeedSensor extends AntSensorBase { - /* - * These constants are defined by the ANT+ bike speed and cadence sensor spec. - */ - public static final byte CADENCE_SPEED_DEVICE_TYPE = 121; - public static final short CADENCE_SPEED_CHANNEL_PERIOD = 8086; - - SensorEventCounter dataProcessor = new SensorEventCounter(); - - CadenceSpeedSensor(short devNum) { - super(devNum, CADENCE_SPEED_DEVICE_TYPE, "speed&cadence sensor", CADENCE_SPEED_CHANNEL_PERIOD); - } - - /** - * Decode an ANT+ cadence&speed sensor message. - * @param antMessage The byte array received from the sensor. - */ - @Override - public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) { - int sensorTime = ((int) antMessage[1] & 0xFF) + ((int) antMessage[2] & 0xFF) * 256; - int crankRevs = ((int) antMessage[3] & 0xFF) + ((int) antMessage[4] & 0xFF) * 256; - c.setCadence(dataProcessor.getEventsPerMinute(crankRevs, sensorTime)); - } -}; diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorDataCollector.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/ChannelConfiguration.java similarity index 66% rename from MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorDataCollector.java rename to MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/ChannelConfiguration.java index 3efbaa696..e08b3de24 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorDataCollector.java +++ b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/ChannelConfiguration.java @@ -17,19 +17,19 @@ package com.google.android.apps.mytracks.services.sensors.ant; /** - * Interface for collecting data from the sensors. - * @author Laszlo Molnar + * Ant channel configuration. + * + * @author Jimmy Shih */ +public class ChannelConfiguration { -public interface AntSensorDataCollector { - - /** - * Sets the current cadence to the value specified. - */ - void setCadence(int value); - - /** - * Sets the current heart rate to the value specified. - */ - void setHeartRate(int value); + public short deviceNumber; + public byte deviceType; + public byte TransmissionType; + public short period; + public byte freq; + public byte proxSearch; + public boolean isInitializing = false; + public boolean isDeinitializing = false; } + diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/HeartRateSensor.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/HeartRateSensor.java deleted file mode 100644 index 406e56c2c..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/HeartRateSensor.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import static com.google.android.apps.mytracks.Constants.TAG; - -import android.util.Log; - -/** - * Ant+ heart reate monitor sensor. - * - * @author Laszlo Molnar - */ - -public class HeartRateSensor extends AntSensorBase { - /* - * These constants are defined by the ANT+ heart rate monitor spec. - */ - public static final byte HEART_RATE_DEVICE_TYPE = 120; - public static final short HEART_RATE_CHANNEL_PERIOD = 8070; - - HeartRateSensor(short devNum) { - super(devNum, HEART_RATE_DEVICE_TYPE, "heart rate monitor", HEART_RATE_CHANNEL_PERIOD); - } - - /** - * Decode an ANT+ heart rate monitor message. - * @param antMessage The byte array received from the heart rate monitor. - */ - @Override - public void handleBroadcastData(byte[] antMessage, AntSensorDataCollector c) { - int bpm = (int) antMessage[8] & 0xFF; - Log.d(TAG, "now:" + System.currentTimeMillis() + " heart rate=" + bpm); - c.setHeartRate(bpm); - } -}; diff --git a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/SensorEventCounter.java b/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/SensorEventCounter.java deleted file mode 100644 index 45c2aaf5a..000000000 --- a/MyTracks/src/com/google/android/apps/mytracks/services/sensors/ant/SensorEventCounter.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import static com.google.android.apps.mytracks.Constants.TAG; - -import android.util.Log; - -import java.util.LinkedList; - -/** - * Processes an ANT+ sensor data (counter) + timestamp pair, - * and returns the instantaneous value of the sensor - * - * @author Laszlo Molnar - */ -public class SensorEventCounter { - - /** - * HistoryElement stores a time stamped sensor counter - */ - private static class HistoryElement { - final long systemTime; - final int counter; - final int sensorTime; - - HistoryElement(long systemTime, int counter, int sensorTime) { - this.systemTime = systemTime; - this.counter = counter; - this.sensorTime = sensorTime; - } - } - - /** - * The latest counter value reported by the sensor - */ - private int counter; - - /** - * The calculated instantaneous sensor value to be displayed - */ - private int eventsPerMinute; - - private static final int ONE_SECOND_MILLIS = 1000; - private static final int HISTORY_LENGTH_MILLIS = ONE_SECOND_MILLIS * 5; - private static final int HISTORY_MAX_LENGTH = 100; - private static final int ONE_MINUTE_MILLIS = ONE_SECOND_MILLIS * 60; - private static final int SENSOR_TIME_RESOLUTION = 1024; // in a second - private static final int SENSOR_TIME_ONE_MINUTE = SENSOR_TIME_RESOLUTION * 60; - - /** - * History of previous sensor data - oldest first - * only the latest HISTORY_LENGTH_MILLIS milliseconds of data is stored - */ - private LinkedList history; - - SensorEventCounter() { - counter = -1; - eventsPerMinute = 0; - history = new LinkedList(); - } - - /** - * Calculates the instantaneous sensor value to be displayed - * - * @param newCounter sensor reported counter value - * @param sensorTime sensor reported timestamp - * @return the calculated value - */ - public int getEventsPerMinute(int newCounter, int sensorTime) { - return getEventsPerMinute(newCounter, sensorTime, System.currentTimeMillis()); - } - - // VisibleForTesting - protected int getEventsPerMinute(int newCounter, int sensorTime, long now) { - int counterChange = (newCounter - counter) & 0xFFFF; - - Log.d(TAG, "now=" + now + " counter=" + newCounter + " sensortime=" + sensorTime); - - if (counter < 0) { - // store the initial counter value reported by the sensor - // the timestamp is probably out of date, so the history is not updated - counter = newCounter; - return eventsPerMinute = 0; - } - counter = newCounter; - - if (counterChange != 0) { - // if new data has arrived from the sensor ... - if (removeOldHistory(now)) { - // ... and the history is not empty, then use the latest entry - HistoryElement h = history.getLast(); - int sensorTimeChange = (sensorTime - h.sensorTime) & 0xFFFF; - counterChange = (counter - h.counter) & 0xFFFF; - eventsPerMinute = counterChange * SENSOR_TIME_ONE_MINUTE / sensorTimeChange; - } - // the previous removeOldHistory() call makes the length of the history capped - history.addLast(new HistoryElement(now, counter, sensorTime)); - } else if (!history.isEmpty()) { - // the sensor has resent an old (counter,timestamp) pair, - // but the history is not empty - - HistoryElement h = history.getLast(); - if (ONE_MINUTE_MILLIS < (now - h.systemTime) * eventsPerMinute) { - // Too much time has passed since the last counter change. - // This means that a smaller value than eventsPerMinute must be - // returned. This value is extrapolated from the history of - // HISTORY_LENGTH_MILLIS data. - // Note, that eventsPerMinute is NOT updated unless the history - // is empty or contains outdated entries. In that case it is zeroed. - return getValueFromHistory(now); - } // else the current eventsPerMinute is still valid, nothing to do here - } else { - // no new data from the sensor & the history is empty -> return 0 - eventsPerMinute = 0; - } - - Log.d(TAG, "getEventsPerMinute returns:" + eventsPerMinute); - return eventsPerMinute; - } - - /** - * Calculates the instantaneous sensor value to be displayed - * using the history when the sensor only resends the old data - */ - private int getValueFromHistory(long now) { - if (!removeOldHistory(now)) { - // there is nothing in the history, return 0 - return eventsPerMinute = 0; - } - HistoryElement f = history.getFirst(); - HistoryElement l = history.getLast(); - int sensorTimeChange = (l.sensorTime - f.sensorTime) & 0xFFFF; - int counterChange = (counter - f.counter) & 0xFFFF; - - // difference between now and systemTime of the oldest history entry - // for better precision sensor timestamps are considered between - // the first and the last history entry (could be overkill) - int systemTimeChange = (int) (now - l.systemTime - + (sensorTimeChange * ONE_SECOND_MILLIS) / SENSOR_TIME_RESOLUTION); - - // eventsPerMinute is not overwritten by this calculated value - // because it is still needed when a new sensor event arrives - int v = (counterChange * ONE_MINUTE_MILLIS) / systemTimeChange; - Log.d(TAG, "getEventsPerMinute returns (2):" + v); - - // do not return larger number than eventsPerMinute, because the reason - // this function got called is that more time has passed after the last - // sensor counter value change than the current eventsPerMinute - // would be valid - return v < eventsPerMinute ? v : eventsPerMinute; - } - - /** - * Removes old data from the history. - * - * @param now the current system time - * @return true if the remaining history is not empty - */ - private boolean removeOldHistory(long now) { - HistoryElement h; - while ((h = history.peek()) != null) { - // if the first element of the list is in our desired time range then return - if (now - h.systemTime <= HISTORY_LENGTH_MILLIS && history.size() < HISTORY_MAX_LENGTH) { - return true; - } - // otherwise remove the too old element, and look at the next (newer) one - history.removeFirst(); - } - return false; - } -} diff --git a/MyTracks/src/com/google/android/apps/mytracks/settings/SensorSettingsActivity.java b/MyTracks/src/com/google/android/apps/mytracks/settings/SensorSettingsActivity.java index 303de6ea9..b29e47c04 100644 --- a/MyTracks/src/com/google/android/apps/mytracks/settings/SensorSettingsActivity.java +++ b/MyTracks/src/com/google/android/apps/mytracks/settings/SensorSettingsActivity.java @@ -16,8 +16,10 @@ package com.google.android.apps.mytracks.settings; -import com.google.android.apps.mytracks.services.sensors.ant.AntUtils; +import com.dsi.ant.AntInterface; +import com.google.android.apps.mytracks.services.sensors.ant.AntSensorManager; import com.google.android.apps.mytracks.util.BluetoothDeviceUtils; +import com.google.android.apps.mytracks.util.PreferencesUtils; import com.google.android.maps.mytracks.R; import android.bluetooth.BluetoothAdapter; @@ -47,13 +49,14 @@ public class SensorSettingsActivity extends AbstractSettingsActivity { super.onCreate(bundle); addPreferencesFromResource(R.xml.sensor_settings); + boolean hasAntSupport = AntInterface.hasAntSupport(this); ListPreference sensorTypeListPreference = (ListPreference) findPreference( getString(R.string.sensor_type_key)); List sensorTypeEntries = Arrays.asList(getResources().getStringArray( - AntUtils.hasAntSupport(this) ? R.array.sensor_type_all_options + hasAntSupport ? R.array.sensor_type_all_options : R.array.sensor_type_bluetooth_options)); List sensorTypeEntryValues = Arrays.asList(getResources().getStringArray( - AntUtils.hasAntSupport(this) ? R.array.sensor_type_all_values + hasAntSupport ? R.array.sensor_type_all_values : R.array.sensor_type_bluetooth_values)); sensorTypeListPreference.setEntries(sensorTypeEntries.toArray( new CharSequence[sensorTypeEntries.size()])); @@ -78,7 +81,7 @@ public class SensorSettingsActivity extends AbstractSettingsActivity { } }); - if (!AntUtils.hasAntSupport(this)) { + if (!hasAntSupport) { PreferenceScreen rootPreferenceScreen = (PreferenceScreen) findPreference( getString(R.string.settings_sensor_root_key)); rootPreferenceScreen.removePreference( @@ -97,17 +100,39 @@ public class SensorSettingsActivity extends AbstractSettingsActivity { || getString(R.string.sensor_type_value_zephyr).equals(sensorType); findPreference(getString(R.string.settings_sensor_bluetooth_key)).setEnabled(isBluetooth); - Preference antHeartRateSensorId = findPreference( - getString(R.string.ant_heart_rate_sensor_id_key)); - if (antHeartRateSensorId != null) { - antHeartRateSensorId.setEnabled(getString(R.string.sensor_type_value_ant).equals(sensorType)); - } - - Preference antSrmBridgetSensorId = findPreference( - getString(R.string.ant_srm_bridge_sensor_id_key)); - if (antSrmBridgetSensorId != null) { - antSrmBridgetSensorId.setEnabled( - getString(R.string.sensor_type_value_srm_ant_bridge).equals(sensorType)); + boolean isAnt = getString(R.string.sensor_type_value_ant).equals(sensorType); + updateAntSensor(R.string.settings_sensor_ant_reset_heart_rate_monitor_key, + R.string.ant_heart_rate_monitor_id_key, isAnt); + updateAntSensor(R.string.settings_sensor_ant_reset_speed_distance_monitor_key, + R.string.ant_speed_distance_monitor_id_key, isAnt); + } + + /** + * Updates an ant sensor. + * + * @param preferenceKey the preference key + * @param valueKey the value key + * @param enabled true if enabled + */ + @SuppressWarnings("deprecation") + private void updateAntSensor(int preferenceKey, final int valueKey, boolean enabled) { + Preference preference = findPreference(getString(preferenceKey)); + if (preference != null) { + preference.setEnabled(enabled); + int deviceId = PreferencesUtils.getInt(this, valueKey, AntSensorManager.WILDCARD); + if (deviceId == AntSensorManager.WILDCARD) { + preference.setSummary(R.string.settings_sensor_not_connected); + } else { + preference.setSummary(getString(R.string.settings_sensor_ant_paired, deviceId)); + } + preference.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference pref) { + PreferencesUtils.setInt(SensorSettingsActivity.this, valueKey, AntSensorManager.WILDCARD); + pref.setSummary(R.string.settings_sensor_not_connected); + return true; + } + }); } } diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/AntPreferenceTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/AntPreferenceTest.java deleted file mode 100644 index b83f4ef66..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/AntPreferenceTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks; - -import com.google.android.maps.mytracks.R; - -import android.test.AndroidTestCase; - -/** - * Tests for the AntPreference. - * - * @author Youtao Liu - */ -public class AntPreferenceTest extends AndroidTestCase { - - public void testNotPaired() { - - AntPreference antPreference = new AntPreference(getContext()) { - @Override - protected int getPersistedInt(int defaultReturnValue) { - return 0; - } - }; - assertEquals(getContext().getString(R.string.settings_sensor_ant_not_paired), - antPreference.getSummary()); - } - - public void testPaired() { - int persistInt = 1; - AntPreference antPreference = new AntPreference(getContext()) { - @Override - protected int getPersistedInt(int defaultReturnValue) { - return 1; - } - }; - assertEquals( - getContext().getString(R.string.settings_sensor_ant_paired, persistInt), - antPreference.getSummary()); - } -} \ No newline at end of file diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelIdMessageTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelIdMessageTest.java deleted file mode 100644 index 82d37fde9..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelIdMessageTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import android.test.AndroidTestCase; - -public class AntChannelIdMessageTest extends AndroidTestCase { - public void testParse() { - byte[] rawMessage = { - 0, // channel number - 0x34, 0x12, // device number - (byte) 0xaa, // device type id - (byte) 0xbb, // transmission type - }; - - AntChannelIdMessage message = new AntChannelIdMessage(rawMessage); - assertEquals(0, message.getChannelNumber()); - assertEquals(0x1234, message.getDeviceNumber()); - assertEquals((byte) 0xaa, message.getDeviceTypeId()); - assertEquals((byte) 0xbb, message.getTransmissionType()); - } -} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelResponseMessageTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelResponseMessageTest.java deleted file mode 100644 index 9fdcfde24..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntChannelResponseMessageTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import com.dsi.ant.AntDefine; -import com.dsi.ant.AntMesg; - -import android.test.AndroidTestCase; - -public class AntChannelResponseMessageTest extends AndroidTestCase { - public void testParse() { - byte[] rawMessage = { - 0, - AntMesg.MESG_EVENT_ID, - AntDefine.EVENT_RX_SEARCH_TIMEOUT - }; - AntChannelResponseMessage message = new AntChannelResponseMessage(rawMessage); - - assertEquals(0, message.getChannelNumber()); - assertEquals(AntMesg.MESG_EVENT_ID, message.getMessageId()); - assertEquals(AntDefine.EVENT_RX_SEARCH_TIMEOUT, message.getMessageCode()); - } -} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManagerTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManagerTest.java deleted file mode 100644 index 01cdac80b..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntDirectSensorManagerTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2009 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import com.dsi.ant.AntMesg; -import com.google.android.apps.mytracks.Constants; -import com.google.android.apps.mytracks.content.Sensor; -import com.google.android.apps.mytracks.util.PreferencesUtils; -import com.google.android.maps.mytracks.R; - -import android.content.Context; -import android.content.SharedPreferences; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; - -public class AntDirectSensorManagerTest extends AndroidTestCase { - - private AntSensorBase heartRateSensor; - private static final byte HEART_RATE_CHANNEL = 0; - - private class MockAntDirectSensorManager extends AntDirectSensorManager { - public MockAntDirectSensorManager(Context context) { - super(context); - } - @Override - protected boolean setupChannel(AntSensorBase sensor, byte channel) { - if (channel == HEART_RATE_CHANNEL) { - heartRateSensor = sensor; - return true; - } - return false; - } - } - private AntDirectSensorManager manager; - - public void setUp() { - SharedPreferences sharedPreferences = getContext().getSharedPreferences( - Constants.SETTINGS_NAME, Context.MODE_PRIVATE); - // Let's use default values. - sharedPreferences.edit().clear().apply(); - manager = new MockAntDirectSensorManager(getContext()); - } - - @SmallTest - public void testBroadcastData() { - manager.setupAntSensorChannels(); - assertNotNull(heartRateSensor); - - heartRateSensor.setDeviceNumber((short) 42); - byte[] buff = new byte[9]; - buff[0] = HEART_RATE_CHANNEL; - buff[8] = (byte) 220; - manager.handleMessage(AntMesg.MESG_BROADCAST_DATA_ID, buff); - - Sensor.SensorDataSet sds = manager.getSensorDataSet(); - assertNotNull(sds); - assertTrue(sds.hasHeartRate()); - assertEquals(Sensor.SensorState.SENDING, - sds.getHeartRate().getState()); - assertEquals(220, sds.getHeartRate().getValue()); - - assertFalse(sds.hasCadence()); - assertFalse(sds.hasPower()); - assertEquals(Sensor.SensorState.CONNECTED, manager.getSensorState()); - } - - @SmallTest - public void testChannelId() { - manager.setupAntSensorChannels(); - assertNotNull(heartRateSensor); - - byte[] buff = new byte[9]; - buff[1] = 43; - manager.handleMessage(AntMesg.MESG_CHANNEL_ID_ID, buff); - - assertEquals(43, heartRateSensor.getDeviceNumber()); - assertEquals(43, PreferencesUtils.getInt( - getContext(), R.string.ant_heart_rate_sensor_id_key, AntSensorManager.WILDCARD)); - assertNull(manager.getSensorDataSet()); - } - - @SmallTest - public void testResponseEvent() { - manager.setupAntSensorChannels(); - assertNotNull(heartRateSensor); - manager.setHeartRate(210); - heartRateSensor.setDeviceNumber((short) 42); - - assertEquals(Sensor.SensorState.CONNECTED, manager.getSensorState()); - byte[] buff = new byte[3]; - buff[0] = HEART_RATE_CHANNEL; - buff[1] = AntMesg.MESG_UNASSIGN_CHANNEL_ID; - buff[2] = 0; // code - manager.handleMessage(AntMesg.MESG_RESPONSE_EVENT_ID, buff); - assertEquals(Sensor.SensorState.CONNECTED, manager.getSensorState()); - - heartRateSensor.setDeviceNumber((short) 0); - manager.handleMessage(AntMesg.MESG_RESPONSE_EVENT_ID, buff); - assertEquals(Sensor.SensorState.DISCONNECTED, manager.getSensorState()); - } - - // TODO: Test timeout too. -} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntMessageTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntMessageTest.java deleted file mode 100644 index 4fda67411..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntMessageTest.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import android.test.AndroidTestCase; - -public class AntMessageTest extends AndroidTestCase { - private static class TestAntMessage extends AntMessage { - public static short decodeShort(byte low, byte high) { - return AntMessage.decodeShort(low, high); - } - } - - public void testDecode() { - assertEquals(0x1234, TestAntMessage.decodeShort((byte) 0x34, (byte) 0x12)); - } -} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorManagerTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorManagerTest.java deleted file mode 100644 index d7817b80f..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntSensorManagerTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import android.content.Context; -import android.test.AndroidTestCase; -import android.test.MoreAsserts; - -public class AntSensorManagerTest extends AndroidTestCase { - private class TestAntSensorManager extends AntSensorManager { - - public TestAntSensorManager(Context context) { - super(context); - } - - public byte messageId; - public byte[] messageData; - - @Override - protected void setupAntSensorChannels() {} - - @SuppressWarnings("deprecation") - @Override - public void handleMessage(byte[] rawMessage) { - super.handleMessage(rawMessage); - } - - @SuppressWarnings("hiding") - @Override - public boolean handleMessage(byte messageId, byte[] messageData) { - this.messageId = messageId; - this.messageData = messageData; - return true; - } - } - - private TestAntSensorManager sensorManager; - - @Override - protected void setUp() throws Exception { - super.setUp(); - sensorManager = new TestAntSensorManager(getContext()); - } - - public void testSimple() { - byte[] rawMessage = { - 0x03, // length - 0x12, // message id - 0x11, 0x22, 0x33, // body - }; - - byte[] expectedBody = { 0x11, 0x22, 0x33 }; - - sensorManager.handleMessage(rawMessage); - assertEquals((byte) 0x12, sensorManager.messageId); - MoreAsserts.assertEquals(expectedBody, sensorManager.messageData); - } - - public void testTooShort() { - byte[] rawMessage = { - 0x53, // length - 0x12 // message id - }; - - sensorManager.handleMessage(rawMessage); - assertEquals(0, sensorManager.messageId); - assertNull(sensorManager.messageData); - } - - public void testLengthWrong() { - byte[] rawMessage = { - 0x53, // length - 0x12, // message id - 0x34, // body - }; - - sensorManager.handleMessage(rawMessage); - assertEquals(0, sensorManager.messageId); - assertNull(sensorManager.messageData); - } -} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntStartupMessageTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntStartupMessageTest.java deleted file mode 100644 index 5fc0c53e3..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/AntStartupMessageTest.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import android.test.AndroidTestCase; - -public class AntStartupMessageTest extends AndroidTestCase { - public void testParse() { - byte[] rawMessage = { - 0x12, - }; - - AntStartupMessage message = new AntStartupMessage(rawMessage); - assertEquals(0x12, message.getMessage()); - } -} diff --git a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/SensorEventCounterTest.java b/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/SensorEventCounterTest.java deleted file mode 100644 index 59affe2b9..000000000 --- a/MyTracksTest/src/com/google/android/apps/mytracks/services/sensors/ant/SensorEventCounterTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.google.android.apps.mytracks.services.sensors.ant; - -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; - -/** - * @author Laszlo Molnar - */ -public class SensorEventCounterTest extends AndroidTestCase { - - @SmallTest - public void testGetEventsPerMinute() { - SensorEventCounter sec = new SensorEventCounter(); - assertEquals(0, sec.getEventsPerMinute(0, 0, 0)); - assertEquals(0, sec.getEventsPerMinute(1, 1024, 1000)); - assertEquals(60, sec.getEventsPerMinute(2, 1024 * 2, 2000)); - assertEquals(60, sec.getEventsPerMinute(2, 1024 * 2, 2500)); - assertTrue(60 > sec.getEventsPerMinute(2, 1024 * 2, 4000)); - } -}