From 2c504fd8321d6ef746086f283ace6cf787640b74 Mon Sep 17 00:00:00 2001
From: "jk7744.park"
+ *
+ *
+ *
+ *
+ * Callback
+ * Description
+ *
+ *
+ * watch_app_create_cb()
+ * Hook to take necessary actions before the main event loop starts.
+ * Your UI generation code should be placed here so that you do not miss any events from your application UI.
+ *
+ *
+ *
+ * watch_app_control_cb()
+ * Hook to take necessary actions when your application called by another application.
+ * When the application gets launch request, this callback function is called.
+ * The application can get information about what is to be performed by using App Control API from app_control handle.
+ *
+ *
+ *
+ * watch_app_resume_cb()
+ * Hook to take necessary actions when an application becomes visible.
+ * If anything is relinquished in app_pause_cb() but is necessary to resume
+ * the application, it must be re-allocated here.
+ *
+ *
+ *
+ * watch_app_pause_cb()
+ * Hook to take necessary actions when an application becomes invisible.
+ * For example, you might wish to release memory resources so other applications can use these resources.
+ * It is important not to starve the application in front, which is interacting with the user.
+ *
+ *
+ *
+ * watch_app_terminate_cb()
+ * Hook to take necessary actions when your application is terminating.
+ * Your application should release all resources, especially any
+ * allocations and shared resources must be freed here so other running applications can fully use these shared resources.
+ *
+ *
+ *
+ * watch_app_ambient_changed_cb()
+ * Hook to take necessary actions when the device enters ambient mode. Your application needs to adopt its UI to be compatibile with the ambient mode. Note that, you only can use very limited colors and pixels of the screen when the device is in the ambient mode. Usually, you should use only black and white to draw the ambient mode UI and use below 20% of the pixels of the screen. If you don't want to draw your own ambient mode UI, you can set the 'ambient-support' attribute of the application as 'false' in the tizen-manifest.xml. Then, the platform will show proper default ambient mode UI.
+ *
+ *
+ * watch_app_time_tick_cb()
+ * This callback is called at each second when your application is visible. This callback is not called when your application is not visible or the device is in ambient mode. You can use this tick to update the time that is being displayed by your watch application.
+ *
+ *
+ * watch_app_ambient_tick_cb()
+ * This callback is called at each minute when the device is ambient mode. You can use this tick to update the time that is being displayed by your watch application while the device is in ambient mode. You should not do a job that takes long time in this callback. You should update the UI as fast as possible in this callback. The platform might make the device to sleep in short time after the ambient tick expires.
+ *
w=2IjFZIAr>D*2A_7jk}<9e*vHO`iEo*av|TSHOZCvu z;e!OH(6Q2z@h<}ks#$9+KW76YE`)F4y$$L9m7uCJ7}mdAhp?P6^%=2MHU#5>L{&9a zUkO5S=Kb1wOjFXsngHWVloodZGZPcpSsI#oc3xhd Y%$rpQtJMiTCcm)NvIRz^*&Da4AS+92= z&^GrENWNz#j>+gSzb#yl>DlM9-6HFc402rY#Zl;F>_=;QR`XPVR9$1xq`>OR>Zm%r zXaPU!`#m{o$%Jn7@#^zS<>!L38 5d-|%_t=*$}M{leakp05L;P)^S~$m62*k{@mv?#2~Fer;`MTZ ztC5QDph*rT)$oJ`O)X7L2wwCS`Uf}=WRV?bNtF|Es^QvwA e@qfy&AK1uV}|+bL|y#hd pXJ4E+8 zS`P4$(^u8mKP#DvqtUN;9fUrRNMc0@+_n1VT#ZyZ3i+w~vH3B(7sR~EiY;YB^1xMM zU_n@Z&Xa #OcbeCxb3Q?kJJ1W1mH1D33#e9iRsUhsJev$1f4M!tPv6dm*or_;#V z^VivMmTCkG#NA%#ZXd!_`%8w3+GB6=;pLZ7vS50TavR1odSUxzvOCxod+udjO$>xN z!R+-5*cpL3aq3Vme$=tAQ$#;TkDLRNTV{R;VWjWCI5o!%v224pX9jePB3>bBK;xT^ zv9L+2HKcq1`69A^;~4(AxtSgc)z;N*qoVGxmy+r)S@+va6fDdwEI^ v(t_w<9w;fg1YBD7XlHjiju{zQP2l1DcEhmUvSsmxwH z?{h1KJ6fH6yA-_ USznV7=T4<~1l$7T*ojP7}FPbwa-qlL2x z6NQVg+N<@@x9Rw4X5B1oX5$YkL_nZBvB2nl_+CIfki9Q`cGcUU$51U0$NgRQi*)z* zZ<%t%4um-8aO_Rm(dEysR2$_w$*wh?i*tx$fe+U^`Yi6FIAnY=9h-v76J>@Z+
$Vq2W7KQ!!c!-G%JU?F6fv^@c?#Z6w+Y?x)o%dF{w|FXOC+`S)3D90 z3#fKpN|0KX#+YdZ%l8e%m7UerR(2afmv=wlL29I7FpOv2KpAp<_Dit?pY&Do`N6`H zL4WK@+eF&6s<{gH-`d*KM`sYXz_YcWX6ZV^lNH(s>HH$sRW&s=-dM7O=pyX;$3M@? zzo|#QT`SPi(<2ReJ3Em02`2&nc~?JtWMV>ZBeGQ@oR5#MNBo|c`>FB_ zJCCQy}c)ZL0vPs{q-MPFNF@7 z1= Qw78(>%dN)q3?Lx7sRFwBwVa{4+z@vkAEU zz4ckPc6QGa8HI|ep^8knf?Qn5f49w!@?M@@Wm);)5kB6ubi9ri>^F!j`b@?^FV-Mt zHIyLidjvWB^Mn}L%k#;rsNCC6?1x$z9YRR9tVh}>g@LsUnQ+koWVvgt3x3M!+=83O zE_xoxa-}rKF#z7$+JcDrYnLX7^}_9JY+{4N1FzJZv18EyOvX`h8xOMNv^4o<>i|$b z(L7asy0s%E`6d9L6NV&Rd#>_7p>M?WsAuGgIIP#X9doaMI*@}y*JCJi{p44yz3J{- z5uo~aWxOAJ!sC2uZ}eAtQTz_LXr?v )Q2~`+utkT?$@8FGA!)LGz8-m*o z|MMzMJ^(7jyWMJv_GV&Yx~khJO#9fV_KxSF_6aDoLO5oIMnuG|@j)tUYfUsX%|U_! zm^pfH7&t|c0^zOvp+OvGUB C)Vq)DDufvV03~w9>j7rQT(V z9If|;Hw;k-x}3BS!iq O;&$#aBxd vEH-8m1>G37?g#BkJJzm *1Kz0NsrZRbzwkK1^5ehXgboJ&d5m#C}kOBvuEs;=yC0Z3HU9Y8Mi zpS5uzwXq8g&eyJb8n-t$exqUdtm_*6q4nJlH(%+ga=ZZUqs{xPch zvp;{j*IJI; zFH?lDhc5zw@}RaIy2|pr O| zbhtN2oRw0Ph=k<9`8zBPEpBh}v0qldq|5%@8Vz(n6Ie(>O>JWKgI2)L%j|UZgs6ZW zyhf!sMu25UA@>E)*Rl{x2n6HsQ)j2iVcO^3K@y%_v1Y4C1 i{&yQd*c#(dPQ10#XJW<~|kR&%AUTI^a#!`g{3?w>I zczNcVfh<>TC8nLRotcpl%YSixep;>!tBFzr;~g%4`DFbN;4At}{N~#2FiJ-W>+9FA zKj;Ukj6S=VG`*VYBtwrbq)IOj8hWBzy~WDgf(x5PeERF+P;dG#8ip9v@+ %9Or3w*jNa|s!uD9-I{mO3JpbRsg~bP{H6R&HdFYjZ4_j9m>b zC3W9FKMF$>KbMKo0jSx~cv8+{tDE2@!!*^8POp|sa92K1S?(SmSA@h{jTgLpcKgC@ zJ!D!g6TLl-a{d|j--`>)o oP%g $vKateX)2JQiP|?!bajcF!V-DR6I^ z2jftGXx&iiF!WkCyOr8vMz#A3Av$ikW#PvY#zZ0SzSFHW%qZa9blE{nbNVRXlf=&c zjg^CA{ ;PS}+gX`nj zZx-NT)hquWw}9OY!H;Gt)aDTJVKs^&V7x-BpY6WKi;Y&4q5?1WJ@i?;_=3X`e*q>? z`Vz_aXc_J(?S%SQJt*jYYc$Qs(D29*Ap8%tx_z*zwSEi6YN_UlM5aBQPj>{!2^g~E zR-0X~&iV@FQbS2Fjr%bHk2wnP$U%aCe!fj)pdrqfTsSouy%QdyNI-DiYhVW~wP8Xg zp2VchOX07USFek?U4v4S8pZU&0{RC&=Z(cQ?}D5NZEe_E5iW&zHnxp@U_P4e7@UKq z5!L|4d*T20)#Jnc=I~pyb|)HWx`MV0+p^fw$JcY9!y$l))^YXv{quW{;I($g_fS}v zLJ!xLhUk=L%2Q*-yTd;~eI6LrtNY^h+13fXKUpPy+t&1IiIhQuc(mbD2g1C*u5S6U zfTZgv9EGM)27?dccX9Y*u38VU7J$V26gYK Rpb%Z$+~=2D9g0f#2FE{O;UE=d8&(Xz6#PQmlMykDs5dJLV! zKi%qrZGJ=__krW%;}iFBJAZ|vKbv(SfLX?=I|zl)FtmjO`O*B`oQ<7bd-<<3(VQ0X zeG#I*lRv$bj#=!|cInyKv8t21l&;IIy$>;d8$UkT0i1PoP@j`|fou1@!0aOc-2)9b z1eNLxs|}b=@@CaYf3pTKhKPfLf&hR8APaZdNxy#=I?);Jq%(`;GQKhzoS*npamW7} z;A+XtDeAQgKLbrL&l$sk_7+$ToX<_Wv$J!TbJEegP}u+P?p-c >-LsPD!gNS4gs8bq_alt|H*n;)A*#A8zO7<^Z48Nr+EL zNvThnQOKel #j>ycm|m7wD@Sui=Z2# za-{IkAAJ1$7Vq9?XJgLvRT8Jx9rm+Tw$&EwP(8HG5?$1@_t8c?`>0u=0*TitT*AV} zF2Ybj#?;0Oe{*$G^b<-09m1@SBINohRquW<&%T#05fC6M!rUtHS8Lbt<1$c@4bz5L zmJ^hQRH@Tc{Zdaw83pPUfVl?Z)!NJq-8}t2y>&!65v&;)AyZ?TM7&+}(o%K`NZUXI z08bOX5wI!Smf(B;MT()uF_cdq0Z+q_0#HnivN$w&&tEV(W{139>wZ&^rGgpDOIrj_ z0L&A`1aoTvXnxQ>-r&_oWwrDU=8TVs1$qfmAV*otbIdF*l8ZLuMOzyec-1NC+C1Htf%qcnp)=nfx4WyxbW;dY|Ma z1|~8WlrBcXIR?^g%jikB{-2Cv>P;ya2ny&{gw;z87RWefIj&uy{C#Zngf9ZGk~`^X zE@;L8=s+KlLu(KtmSxiUiK`e%NWjUE!DytPb&I${;fFM002FG2Y%koc(ij$V4?sEt zjO&~_3CX)tD=X~#DnNp*j*UTc5e`nmF9_+@=7trcOXpMy;%es^%3?H<|FcYPSsVd~ z9_X8p{!Gry%9>Udf!{8PD;J~IV^Bp#qd`kYM@K_L!^kLSyNUnQd8qp4O*e}qMkC>W zHxbLBTJZ_U5xPaBDWGRdKYv11F&c^g-60X5JPZTaDGAWr=%zX#8pur+N?u7uGf=1A zPv9syv4!nK52K)t_&>QK7|v%F6Ehh!9RT{r>P^}igo7m?RbC-S;5!IevRjVx>gefJ zFUmvd=@m-*P-y`|P1a&Z^zT}PfCNTS6x}>6*Tn4VYMmwL?*6_(c3)&8S~?%eJQ%Nfmxr_a?xXZw*h9`F8U}#K3>aP=WP5me79~#4%rujw zLcKs9)~Ps(N**Z8+esYZB8dvrn&0$2gMvD@sFT(*Gf6s$0fx)5lcs@4ftih<#6=3R zWc&}ojqAU1AZV})^9W0Zp;XD!UJ*B=c-s(Z_M6^ITbOJE%&vU#a|K;(?N mm7u;g&NQ zR_#pT-YFlHkOpkL*{A;Qe~gYXPni$<-!&ubQrW*v$tstIFxd*m9)p4J=~1L>U1oiQ zdM{Xniw~=W$24QC@_wl -yhzwVNFnS}Xmp#{Iuu z5t;Dt@VH^cgv_h|hGE3AJt+~Cfq`X0;zhWw=5Lu|MAgtZf)+HIsedfDu!I&24*%ym z?8%b zhs@B>&=lx-Szca_i^Cd~gdizR1k)fzMnguJiK6ZleQDy8>&tR#c(}MiEa~a#hh!=t z3N`c#vW=KdL^jY^%a24k5}<6^6 dC-79)E*?!r z4y7mbF8)S6B^^-&-6EycM`^(5W{QQ>RFhf|YGyDAOD9V=Ycj^sa3B#77_fjfCh6}Z zAHfmQ*bYLlz_6saS4g~Q?5SIQ^cx8NN)bfbq|)!I*OQ~dr(r0l(yoY|ZS!vGes%QS zX=X798s0IxbB)AKN}05Tw;{C%23QFhSE&CtNuqp!pI|4_gRn+2)HQ68c)S(Z`~L15 z_7}Z#j5UN#PwLpjwns^!@Tg`YZSBSs0wmdgMHkb&zAz9JYDWH+LkN{+`xyXYc+?U~ zSnU}I(f~|->9=n*9AH%v1!>N?rluw`LB;<{rUvysl(QkDSjqf1r*CPjQ>y43{&4-} zYoWZiG1iKB8;1R(wAs;85Hfy9sy`tZTGmlLi| k^wogUqIH;^(V>*rU(Kz+&)+7RX0a!>pzS9o8X z#rwFDg#-?#H*`+8|J^+N1Re0w9-5k|9m?3nSOiS$8hW&!el9Kj3Xs!>4u)*e73(b! zuz`q~s!If{$EwMx*AtMq*L_`HM*}+nOmTw FN6c9_sPey&A)=pmFDnaHFlr2*48zHe z`HHHZ6~XH$)YZ1;*=^&|~84s)(W^2>CY>)quype%&qV1UgcvyZ<&pwiaT*<6ggr z%)P~U(JSHd?+X9*OVv@xlcxBlfC=Fnoe70OWzuNStFVRj2T5@mFZ;hR97nN8Cus|5 zzn|bscKg2~3*H0@dzmFiVNb|-dg%b7H6- ?~2ZsGW?k@&; z0>JX1SkEj~BTPn$9vPYt{}ayL*R%gBZ6|no7e)S0Ae`jAMly>1_v8P+U!5qWclB^; zgWdsN4|a$J;O^p*Sqf~ZxT#N(C`N742Bahz4t+`zHVD142Q(+CF@eYn J!QUcIxz@a_8z|Y#vtpPan+FIN=6=Mckc>wgVNJ*!GvZ(i`2$ghq zcYpe%MIYn(w6R2BvO`FT5Xi_JxM?(yd@3y?2H5bO$v`_>TRr(eqb4CC;ir!u0pu-L zwSq;m LyjANzYZ+MAV=&h`*uu$Twn-s$%n6=9J1O?G; zD`(xhByi Z&4ok3Qlc4Z$M9aWH*S2w8d2!jwwS=4~6hvi~KPb~1F zk >|UtJHY?Ct5g+K30r!2alG1()Aq2^rPVbf1tK-?gC2M8VY_^`e@Z zZ!@#+11E-14!J_=In8B=>GCC6f&P*lBs xgU#2$lT9tHaj;Lr~7MBByMO}w6J7=WGK5?7sTgW z%MGxO8iP*^f`X*pmLZ7Tb`V2zYIv$M7TKqMxcb*Sl _E zUh0`24eDI6hZ7P7Rx2r;55ja+WhDj=b{9#N61lqk-oe3Avtt$xyMv?SYc;#&a2mv| zTO-#_e((KRTnd4nx^xt5W}tJFfE#@# U2HkP`-&b=E;^vO z_}7j0yWBF-MSOwi#G3$7jM#wn6Y5i%T7a{8{xZ0RjUm_k6+nF dBi%6%YfT1QR6l#72?(o+5M@1X4i&wc!aUMWA2<9b= zd_Fxh6yIWNf$rXPIcr*hOfC Dkq*JcYDHTmkO`B$O2o5DQGzfecph1vWne|t!EG*RP $Tc|N0BtExAQFQ5x!0dhYtgjRfggPZfMePmLt1Rut rAUr>rK5KD3a n65)Wu{f$^%k?08lc|dx;l>7Tcjs_7+}021uV0-=PytdPq3l+ zV2Wnu c^nl z3(xsYpmDDNDCdDhcDCy#`~^i3NPKd78p)=7?yd9*Rdk^ANp;15bicwipwSBDrUb%F z1|}x#3LzYZx> hzf4Zy-2Dv-m_NN^rn zOoM{N{J#KTBI}g3g80pDiOtu{>j0Bxz*H~iLl8i4)O+ZLJs_S*1$?OyNfcC|j+7CW z6tG}U9hv=QLjWZuDSBQb Px_xN)SK1&th{+; z-n$-fAPJKECGi~aZi@Ew*udE1dtm74#`` (vBDAChr+uRmX6} zKw}t3xno&6Meu2C*b*R6f)xK37RC zg^a-nY-NN`Movzy28WT4LcocMjSc58$_uQ|b+zb^F9l4*;L9q~4kEP!^(L1^-^9zu znxtOVv)Pv878Gt29TaOk9O0O+v`~8VSGX0Pe>It(ouU}?)6*akzhX ~u-7T693A8Higj~_p{ z`En-#kV_>;fIXx>VX`NzH*5aj=qQRT463=oUzd^Tn`mRqGPnOj9QUlft*zlDkHM?lw2~+~ z0o2ESvbNq!CQhPo^Buq;94!!|zlo(GWu+v)5n7>)&U6!$0f_npJVunOcL3@`#i+_B z*-~};Wyl35U{m9SY{l~m-!(CoEtNZHcn+9KdfF)beq-ORY6(-0!a36C40cxg=>A z8E8ERd|KBM2uyN@EkUfX JWaBZ71S=Rfi zIZM?u4Ot(AY<*M$t^W#e8-Ovtef=themVirI47$C$6~>E`jq;Wn4jG+i2+PyIvVM( z?*^)rl73F{$B!V&CXo-^UjdNZ?%TW5w{PyGC^Md+{HWSkN*MVQ&cY3vRQTy63*`Z; ziUyY~kWTzgy8K7jA)>F(tnCtz$uI9O*Q!fAkVS~|glU6+fWYLP5zi40o+As3XsMz| z;9>1Txh}Xy(0QcL{_dCaw1tTJe=tQ=u--3Cq9*LtuTnvJM7lZEF?%xKNYpOIQBtG; zs#H<3cBhp#o!9xm6xi7hy8^MNu_q&W$((BanB;Mc->#61VyiIUS+SH4$7vXumh3Cf ziWA(4{VXZv8r`mbCJROm!QBF{;L-bDLqc}rxuaua{s6!!(vsrls*`Jw_PU38>_--q z_QtqB)Z# )3Y*(q|f)q_WbE AJ5y{ot=O6s1 zFZ2KNc?U}c#25;!a|;Vnf0+shfw43J*VP(4&eDiwwyDj+OUa!`vo9ziGocv4jq)Au zeXJxn?0Vp_ifK9n=a$6QiZ5eI|Gq*vpk+SA2bDig0t1)8xSYh_N>B3Jz{?fi py&jRxap*6Zi1k@xH%ehf-Pzey_u#{ zGD!x99?kS X -iYxbiex9&X&!kN z3w0)nD1+koCCToul)WQ3dr}w}7{;7?EpDFS(s(>itVDf4mO_eY{T%E2WY`wHHy3uO zVXkGsU^XyV zkLp9#s!a8y*$F7u{`*R#7nUrGbsWzU0>YY;(}l= ;}+Q zyoG1Ddb+wT{^t(#Z#E*u0xqm=Y*xD8m{FF-4-E|gNn~vF=1abZ{~YGe0#1}4ia>vb zTQ)Fyqg}_4lx&p3VcJoN$1e?>=U^h{h8+A=3g&v#fGeC-{F}~}pgY<^OrU%4NV*Qn zsCx#uZ|e~zGm=B=;xYyy!C~0~mHI9l>EvlI1W+Xp{FptHDX^)vS6B83`OwjxLcM0K zx2iJuD!QkY(LbdssI@bL$3F?zhD$LeklK-k7Nq4Wzkxt7il}d*=V+~;GoTB^Fgp6c zjd%b#-`?4wsPH?bD(zmSID4FIMFH9_Nl9M4>B3iL?X`jZDpb-@WjN|70-D3eq-82G zz8E<8(s$t!{9Za?4aPoFYyvAPk|RblC=m7Ur!rH^ZCizmK1RkR3(6Q6{20#@og0l8 z1)6Qc-+cbFGf`b~9`Zql)%1mR#RUI&c_!yiGUHTRrkRyouh+hGl3he-n)+%}xY$v+ zLqE(m^GAF-k82xoX#MRHKDmT(qn{Tx*bl2$)Xm4VtBl>EZmtWXsj-=M=&PL;{{YIf zUoaMo>o>2A!*q+Iu(6w7nqib@0PQt+5TTQ&X~;gRp71Iwy!U`gymPfPiReXYr#y zr9(m>F~WX45DdjQ$8@CBaHy`d!j?RPM{>PgP?H@ldy#V-;F~j8^{Qq_DvSXN8(^R7 z>(wa#xV 0w G3F%Im=p>`eEAHyRc>t=h2%-dxmO@?zcbFaTp1~@=X_nN|ZoT>nnU@Y{j8H)| z!+u$+s^7s2G-Uy0R{&T$Vz~zi*(Acz^iXgay(~1eD6*1UdpGOUikSIrOhx|kqQ5$? z=gzne592B`C#Ts*Ys{Y&-Q8xCFHgyV{o$u};TVpkA&19J!>|USwA5zL9-; WkWT%Ybv(RtrV;(L&?e(s7yc24{`E~QlYzE51MukZTL z4lge+Fn~69`k0?gp>H0c){p4*w(|Sz!A)3AG2_MZRBbfR=1^jPkAyvhA|z$svA&a} z{L*qr5b&Hd&>-?5`bnd!!AX?^mOGe+ Ip*?_(l$30Knh?+7vIsk4Y(cd94N(5QzHTJ$jk?rO z6~vr~`sUH}2HRg_8NhVuo3pK02UKLf2J^{U^hAANf`2wqZ1JPb*XsH%f1p~jN8Awo z@5W|918GT)xQqlCqGBacmL_$g!cA>3>1qzbq1Qsp&or34k#G=gj3#mYkG{9Yxz~pc zWa;)j@CgWz5D@`o8qog+G%X$dY*rE`T%vv^h_co@HRu4FCi3x1@1=Y-545D=-O2<4 zS*QHL`Q>Hz`MeQXJ&U&$#cI&y3Q%BM45JNT|7R=N8tk!kFqCfE@dPD;6eJ#3^yJOG zv(Waav^jco>ZCxc#u3L>fHU0Qww3=pFfagkb07u(c68*zq;!|Igb(p^bgX_`|Me2Z zq=w xo66l@Oeu4b1b>*GdLPfH~MAN;waB zUU*W2a0xiU ll;;K^`ii&Jl-`)LESonG%mQZnFF#+%w=A~H3TI{gEkf)bc zafbVa*-kGArfkae7b(fS{!)bd{@cv=PfQ7A9uuvvglcH{%`swRVn$kknXBYj42dL8 z#VOK++KA4<|5e#nhDFtV@zNnZfTRLLBOQXEvzmF07A4b>?Jc80N}$br=njAEEs_qkl2_08`1qqo(v@Cc$*Wh1 z@S|DgG8>K|enb{@CV~o4J$w+sbDFF$)ZA;EoanATQhIqOgohb>kxBJMVhW1*5zkfq z0DT_~l4ArRJvyS1JJV|O`*(3Mv3PCNC(=@Zl!e;5x-6yI>r}LT-QAZ*YZX>`B{hFW z$5oY=^C~IX6|>syt=&_BLN7c*HMf&EI_A6tKR>CPMeYV!9)Qs%!t5u&E}~S3f&D$u zZ;_IbiG{PGbQ-NT{T*YwEJz<*P91y)L3zH-OifJ 0|X|YIXn&0JWT*9<^*X2 z_jWRGFF`KZ&6v!gmhFbY8aK$THgWUJg{*h*N@J$g+?Own_QM8S^k@b03kz%4Qys2$ zqIt;bI|7!h($uwL@UzlqF l&CO?i zpZv6ZmVqYHreZYI(TQ@Ec}efqomo(j_!#>#*E@rOS?Mz}Z=+mrYXmQo-A<(5;-j z)(c)4V3Lw 98}+4YTzqHN=Urg@L|?@(%#O) znAKXmFy#YOC! ?Q@Ri2uzW3abe+G&?K`A z<9nr)ET30{gM!vC?l@=U*CxN>_DTkA-=r_*0dS<^;^M#%XQn~d)O4!%_Q~uRcWf+p zGx))C@TH0+EM8A#lgYWmQ*E4|lLI1k_S?li+^cLp3JCG#ztC;AK$ gsOF;-sNO3kQC>B~rmTxk#Ea3-SmtyC*`w5%dq_1FWP}j(?Q=Edu)yM4#ZY zV(fn_=+Se$-R~rk&@o62xp~vm-F^1Wn}{qgXc*piSu!!Xdi81Gn%0K+DM|XK6HUK2 zkG2@qIhdBnFO{IU?W&kw@m%Z*-PqXpynJM%5eL>R6E9v^R`XEgNjNp7P7i|=Xf{SC z+LZiBJz^m6>%3GrBM!0(OBn_gT_YomkLj=ByI|{)Do#;Om3x?=@@MxRlpj J={*dQFEN8Y}u1UC!)f_rZ7D0NqgM8zPl=`qnYmRK#B-f zEZ%F!xHuK6MXuypJDQI3b7P14`%WkNYT8u7rqS5aQnlezawW!!)YzusZ7B0CIT+}m zgQ*j>VgYO{EiJM?GAYT)%T$KM(25tCJJG`Qdb!&(iO`T6qz8kt13{k1tG&8v*s7Aa zY%NVVzJG8~%DR`fg)~=k7A2ib86_MUyHqTUEwEiyu^rm=$fRJTr6HGW>nG4ym85Q^ z&;G_nL#BUlCA_P9Y91G1Sg2|jsvyg$Qp7Gf;MEC-F@?Y}P}o|>uY~&aP_1i}5f++i z5aQB?QA4E_^|KAYHXqX_(M=+Dc$N4dgSk}(wr%3)Grvh+metlK{k)nEtd%68NzWte z1nJm FW|A%aqzbbM=ywIlW_Q{PgmRMA; zA8p_m9VjFrfjZ;6eyzD*^;ysE2#4O&BjY=FltWmNun+G3`BB2psH(!F-8MTZyU6ud zh%^J$oLFgQaF%d=nPr3jE_7KHKTJ+WDOlx8tL~*efYTHkKrR$zs52HN_yaXG&~(&J zwhd3W26#njcaPwd25oL!97*M}BR6A^O$aPx*b^w(A|XKqG3-Inx(+80QIdu_yq73T z>KuyeiQ31(Lcrv)y}F#Y0`9
x+1~;Ih|QF1KE9V*f^WAB+>IpIL)PU z4_zNri7qEu`8P%{j#&2CaQ!OopHZ7% (xYLKgi<+ZQBo3{ zy SNh!u0aQ(WbRPBqJ73{11E;Fq Flr8SMVjbl3~6jbpMU8}V% z#|-(iPLM>sK}ULB7$o@-m&Ra2D$3}=%lhq1e_50SyV0v5? *#TE3ulLG(Ig}q3{vW> zvK$}D`48IU1_np({yEt$C!1&9{&heL%Tt+kAjOLj0xQ4+>klReUJWI6FjiN7;#r=? zFxwFfyE8k7gg!j2X-%#68J-&~O};;y-$A6|+o^Q(yAE;IXw(nZ!Egne^e^75g_?|y z8O$>yjh~P^>;FOuXPL>|k&|XjO`MWW)8e>%R1z=up)*iJj&V1^`Qr+h-(mB(ACe?Z zAhY|WlSQUn5ZY{F-TfwFP3_%Y3f$H@44H#O5KKDpgN9xqa0pC?((qeK*~AY`3|(G0 zDyn{t#p?|bb}DiQX6wuR(kYLX?NT(pGix(q-aapGFRVHp@*teRWJoh*(nldzl0a$d zNBcv+W~iRuKP0Q-j}OJg33H7H%)3Ub(Xdbtcq!=ck1Evgt2s(bH{eGlI{l0Knn^4! z`i+ZF!vuHPa3RBtfO`GP{%`aw`U9LMrd54?ODpKG2q`shZ{e;AZ9+m7L3X1oXiG;e zb%CQ+`UEn}kSX?FNNz;M4?^fB+n?6pqQyN#V~KH%l;Dbti(!6v!MY~SQr^`CpikI zl@po2eT|H0R~5M~MKG5u%j6Mu6|_>H!4}}69Z7r5eHC_JtX_pLi`&N84HYZjW ymkHSoCKx6nAN= z{uOV9oJ>KxOyag3X`ugJ*Cm9&0HfP_-O6ER6EN!pH0ikyAB^;k3m~!;$azq5JC7 z6cfhv$b#*DCw9#TpD*R^lt7mWQ1{ZCYr(Y)(0uJ*shy#}2 U9Y5RpbUKfY zk3(ZHA0e^6t}FBokgK5@0=c4pm;3_0KFYVdf>@*`AcK`^IL)R)#W0`=Xh2q=w(oyx zq_GY#bSGG=LB2Cp4jED- ?0XC-7Dp{HcyXQwG7~8$ckrp?u9auZ KK8=>u}
P8P2 zT3liczB~5aacF12Bk!$>Nl8h-cBV_Bl8x^j-vQ^a*IImLOiWAwpVw!romVcBzNY8v zd!d0L@U<4sn3MKD0Cp8esg#e`v-kFbSeYdz@8PMOijbTGKb$#1ZIWp(NMR;rU&p 4(i%88So3>=h--AVR9!R)^-os*5J%3uIq zS+ft8#pJanfkFYWz3a1GZtW+o{yNwidU;0ULoMsB9{dXqek{Zq6Fm@5#o}z;y>av3 z6$bibd#cC`d767=(@myO=t@X`L<|Qzq zt-IH@-Za|Pg(iC9uQ>_qOB PF(ms{l?x0^of;p-Mp)Zp{9Zpf=1C^g2s#%m-pG5 z?#tr(2*ZY$Q#kOPG})6;1mQ0~f+%uxVg8;(?~%H4YbdyY{kCGrHjDwz_El75X }P&j;?Y>8qqyNv<3nHo(8)qtroc%}6p{5aI=o1dRgY<+g5-#c?T3!)D^ zqna5v8E!`~-nzgQ8Qh^*ZV1I~t^F!7uuZnRf25nq9%}Txo157pOM*5Pp9dg<$H&Lx zY4g;ao%{YH-gGX|4})Y^N~#s_0+6{w{7u?_LE)Csuv+){d# eGlmB}ScM&6Kdtn7v=AT_XQ }%N7 zbqx&`)#GILPlNcy#0&*i{1-ZRPmhCN)ANO>j(7ifsRYYUZ+Sinvb#-}%@*rVNrJF) zQ=@79$8&@)7M}LI3|<=_I*iIjTe+dpkgEMYJ^ry7H>@-~JPak+SznY{I}xQED+j(4 zPgxXJT~(!}tU|0n`AGt%_^{>GIytR*uQ2W9MaoYsRn{u=XWL?ZGO?K*A8HuS&aqa< zf$ncXaK+1Ez`0GAjRP8hB87~7ZSC!8Tq=J+CFg3bfCleAc^K4Jm+Ub*PG?)&`@PzH ze01-JENcpSD6cC)WWYBHi=QYA%kp1tXs!$;jjcV9yr?Qsonv(RC~VjDia}5Cr*y@z zRT&tQ0HlV6($~fz( I6y+c*?0`=3r9uTF@^}qj zAD^rbG`gYB)ifk7#C4xTr-P>9a6+Q5#+=m&7VM}sTNI0v{?-|ci(SB%=}M?N_4aTq ztO$1iTSCd`>s;y mIL)m{0T zqwmkQ_uVOXg8oA^USP#sztVOwwXUhj2$YGXm6fDKMoyj-V=sCS!O#GAk+s_Y{S(9R z2b}~7yh~5Wq2PmPV41*v=JU09$#xBBKE;qy%_gN%EniE^=BMLQwn$LqY-@7fnT=p& zHh@kbsH^n;;FRGQF*G*LZ&rz=cl2xl#vR|20fkWL`Dmwenkoy93`Dzodiv%cAMLt@ z7V#j@_K0G>LL^AUF69?3Q#vU@!=kIMPOtbS>!-bqiIK4^kfznf?yF`rDt Y5N~eu-#M> ~oL;cPZ|MMmYX-SF;c)KzTeYE3j7DFLIYNh7@jpV* f~ywx;N-%`za*06WJ4~x!+Q*=V<`eku2 zBvyx_J>|0qp~K_kr;_4(agLhl)~iHT@*llQ5-b-MBc0 zP^swDFolY&Qw0pN0OE z7C9vP+3s%Lj?qA|s4n!7NtPKlIrS;4sBk&p?nzP2+PS!_OkN6J+4!Kh$_u&NrfQd3 z2bg;R$mt@wg;wBxCp(EY3Htn}%DCjuT;Cr#t#g7mIEZK$dqS=Q>gw_<*;J>Es)&A} zF>GOT(}xduj_vtbe0hVW1BRP#Y1h5(VifLF^4$S1#cQ{tDaZErLzw!Je644|!ADh> znJT@-M}dItC)7sGS08H?FBhm|7=IZe>CwtYc>uC)ZJLXEL_JQ*PT|XVoJ#RhSkF~B z>k-o>>2l0ogyy=wrK`wje#QF4rVT?M@ECNuc;g9uB)?Pkn{D5svJa)ct{Grm!HNtL zeZ-+~@W|qjJePaMtE0yL)fn6EumE&r)34wD`}?OJ<1lT;Locr1l@9djThtd}qu8+M z6qc1Cb>u%kVbJ!Q49 H08j PyFeTT~afaZlufyZ7{=h$*m6oyzK z7rM?5LFP` 1M&Fm;Hs&)+&Iz_K7(`GL+VYU^>Wai#LGkieyWi}Sj* (m+u<)!& z+E^mS-l_V#1{|2zL^a1y;blF^s{Ofnd1N;_NbDKNBGEwFHNTuKH}JjGcjlERp?jSh z1qWC=&3l#yOUJm}gvO)3e#*n_$zH?err@^h>~?!9W^{cQ8TU)MFl6~k9EfA9D=P;I z$HF@VGJI3cib>N7{yI7NT}*eeUBrmrs0O!anW>y>JJT=e9&^@CJ~ttpn~{NLZ#XQ9 z>FjU5OW(0U<=$*RQC}xdKCn-4n`4Cf7hTgXJ<9X`ucZqxZKsRju+5<()lyTV6Owf; zdJ-j3&2|0zw{II)(53OP7}FuFG&G3jQsjWe#b6*lcpVF+M4ub_{zZ^A3T!^(lcCNg z_(XD-Oq=v6*>clze+H8=hHrsqFB3&_Y%`pK8Om^wj_%a$p}^*bT-HI>t`IOG3?haw zG@JW&sZd`*u$c&}z0jiV19T#V*r3DA*v>qOEaJARfwB1OI^hi8yDn#$G1JG#MdBC; zyF^;07-9t4ya$?as7ep+;}1Wr#<2*|K_etr;QBMWhL;1%6MwkPw|P{52T=%|w(AP{ z3Gq=|HHP2fRFv0w4o-W&tN2pS95MNfLN%WUO11K5&+PbPmbv~OY2UbUSf-hRm&KR3 zGqlLe^M5V4lR&{4i5scnnGzSEBbg)3uj(o03uWt+<=ah(3~Y+Xd^ym3q(U(8sm|b7 z2m8Au>}nFZZk!xv80f;2nJ+8{N_Cl3ITJ#-E)|t3l62fWbL0{H(~8-x|5EOc6vnhp zQT1L_25+H4pULIXxe;g4dzBg lJ11$yIgfwKP~YW&^H?-RZH2=yw5B)oP)@eRMU{+jOVV=7UT^>ZTo ze8U(`I+YfrNTvZJVF&2$jROM%!95P@s2oi4d2r>=c=~y0>Z_{-!AR9%ZX7$*tYUTc zH7KDd^{&X{AUGW$!#}6VpI~_JoYGl`#$FdrKy?Hgj3ql6Q`l)~_+>a(l{M7c-Vs)x zeCW9aBH{Bg9;wgGgiaDgO#);*U&fUeLlk&!Ruvb^Wn_cvLOHWhzTOuT5*E(%t^Kp9 z-s(uLez}p=U<-_w=|3^84FMneCZ0%Sta-Mk a~hEvPW5KXsIr@`#DiRI{q 3sI_R_;1;Te~(XqhJ5nD0z|s6Zy)RDiAK-Zws|p(;8y1c2}S-B zfDyf{`5-BoYv*1@)YIS`e*?c5m;U~_+1UdiPxsFcw?Mp0u{23U%$lg_N74HxY|Bnl zlk~p&=)}Yp-S@4v8q{#&-?)l{hnK@+vJ=Ibq#Zs|@wDX3o{^KR09p!IdyFqUFzq1? zH+^^n6-evZ9a)}2#7 #!7n+}fT?o@ z(-UXTdMCgl1!*l8hOpWWIuROFiBAFjzGgNMc(k(u3Tfj4Nf*#x)2IBBVvkBI>&MV= zOfuaEsN7l0q(%)tx|RcM33gpFB uknoL4;8u<&-x4aQuK+PJ!HEPcFdmNIzhpj+m9!d2 z9?9>aToo02-HbPuT4-BTQ>r=Jih!g%exTpa`7&6q#H`r^6NQ>Oo$-WvyIwTl<8yfU z>MOVRr?f?`1XtxmmyE!#H1xkI6XUZoWhh@jSHEIrW(Eu>qRv%gC^979^5GQ8GFW-~ z$s~2a5GXEOH4Pj9T*?7rFn5GPhfB3+Www4lM>xY*D3*aVm0pCt>xHZ$skCa^_YG1d z4I0l&SZDjcQ#cNusqoKJ741{y104gm%Ty3_XIhxjO}xCkRR1HNB(7_y5?Bj0qp`|= z27a#5B-9})S}agvK>9k~(&T_Qr+L&}RmCR0Y;M_AJGS^VhC>`mh9BVEXri8>!2 zH`}^cAnuWK96@U+gv!NXLTct5LOD6`gQs-h#FUFH&aNwqGdt(CFxEuQ*7^vV#<0H( z!pgu?EL^s$efspOF$cicb@p>D%(QgpnTpR9)oiw5G`iHky!2n{O#_L$!g+q4b$~1H zaj9Uu)e;7t iUPPnGdmMYG*IYNBskfk;zrP>9I7>C3qFV||QKNRpM( zfK-Ib!;Mp{GgewCsZ{vQDyg}?8qCjRNgeC1fn;Nxa!o^n-)LZuGp?TX^Il6H<+vPz z88ArYKSyrY;w7Sz>W2Stvl~5h>#wPT^L{UBvENJW>h!j0N|I$M<}v4IGr-mbmaV4e zj15~lkge(zOMT{B>Z?aAI=Z@FKDAq@yMh2`g78Wy$R(oN%|OCZ{l4i|M1%#8dV`^l zj|c`S!eEB{VWGgoXJImQmG(0w;OUf)a=AZ(Z@_Wi-=BYPeCgm(R8*XmRu_E^Z~Z7Z z?@WTXYJY--+fOozoW04~XDhS|I#6HbyYlaJG8#!Fa_`?yUV?%KkfYf*AU(=saD{h+ zL~uX0KvFNO5Y>?I;NHQ_(&wkqAo7J=9C*U8x)8PKXo@#9UxR1Wo* M>|#wxM*;%Di2rK;tnRH_&ysrxHpgX$ 5j`TLaFCo)KfoL5mw-=yd8by(C-*t9Y z4bZ%}X&XQxwirTEuS0^3GW~R{)6eb?7KB9N1|4yX2>-zdl_L6;fJ%CGA`GlRk_IDe z)A}O;i%itc1)njwt5qHo8E!@1Ggxp27K-BA%yie(j2BXIkg>SWbn#7UA`>xvFp`8& zTJ!ao2v`kwc|>)dSS%%yEa-tGfi^*dpCU;Ofj|u2Zj`xjp&l<*gI8t5!<~-mjqn=7 zEbe>UFHuI`!enij8O5<|5B6zSOnuo%g_T2>N3okIX0*j_>RMUT%F!kXf*kDB3Y2Rk zzh0nAqBIiEIs$|t2-|EbwKT~t1kDWnO2WCHbs)g6lCy{HiX^x+ YU;?1kogV z(o^--5D&Qz %IlwA5#ep8SaFcOi5nr!48y&Bt1Ac`@#0AjY6b&p~*v%VuD zbR8zVK=gp>u3c?a6^1AsM^2kij>W3-+nW?0fl3j_g@39`=~dvfzDl`D?V~F&kLuS2 zhGI9gJNi_EFq(Bl$hw^ix=+bzKi9THd(q(%QYe-pdF-?V+fl=R-_hZa9yFw4pC!Eb zxt7MaLKH#XCvxF}<^2p+Pv~`By7cy_Pb+j491ak7@oRHgiT%oAWpu{0j5|@50QjjB zNC~p|fFnIin;9T7xT_%Tt3G+Aq@<*;uP-Al9d`3#k_=$2?mqTd#a+@Th$NMo6;bV- zb7{{+rp-gxKX;pwEnIWz%=Er|Mdp*lv|iaXJZtV*lhSV2^U&9a2o_--7KanBn!Af@ zRg}76FFh+8daYN3MthYGcK<;72#Y}@NxqexT|JY%W$w_*GRLw`q+6uE5$8?zh_JVN zs}ICk%gHVty3OhR?;G=axR1^YS-H9VGtXNOwkKb|-Z;VaiBl2^%6}vaW^4pE36L^f zrM)2w0%Byv>af1n>F=9S$>X87mo)vo2>=R&l{%XFR9sS0lKURNnk3tHk4$u3%b5)Q zqAZ+9M4iE0gVV3H#LK9AgO8ZkN6q{w_@hVVqB>CqbdT!`R9a@Zcgf|7Hk`HB@a7Rv zM1hcrCl-H`rkFcflwwnkiK@5M{M7W5{M0!g=`yh*&7PC^^dl)Grd$-0EKN!&P!2M8 zG;2zY+>zvgwVeE>Dpom>sQt6oJPm>aB0~F|tJVJfTs&E-7ZWD9P?E~WCy-%$Z&^jX z@-|tWPDrkh*p)?6Y{^baCGsf&a!6SvJv5Xpiccg*!HVT|rSF?dipW3*V!h3`N`6L9 zYDoD((fA$GJ$0Q1X$1u#u6JhMOHqC?^I*)NF0IF}hPPzE?9ZavU*-fD_`H@Y17R_1 zZede0=>1_f;d|5oOsq94GUSq>#(0P<`GTE;)EF7c{nSxQSPzoIE(2@pe5oX#YcVez zh6vB8;Vl`$uaY{8y)AQe*p}(v1T`xG=sGEqt`ij`#8Ssx9&GN-J99 ?-^?mOq6@ 0e{_ z4}2&tV_qOEv`oUBUFwb%m+I?66Dn5{KoelE!0+|b_}|X?|NCo*ZvU7_W%Az=ho5U# zWaO!(r3Hc=y%Rbga8k6SR8P$Pcl$68=+^_?5F#UVU9TMz?{isM|L=c~@NdWB=dUa) z8 g)-&z)=yW*;k|eSx|&9)CUxhS{{t)xYFPjP literal 0 HcmV?d00001 diff --git a/include/appcore-watch.h b/include/appcore-watch.h new file mode 100755 index 0000000..75d8e59 --- /dev/null +++ b/include/appcore-watch.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __APPCORE_WATCH_H__ +#define __APPCORE_WATCH_H__ + + +#include +#include + +#include "app_control.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +struct watchcore_ops { + void *data; + /**< Callback data */ + int (*create) (int w, int h, void *); /**< This callback function is called at the start of the application. */ + int (*app_control) (app_control_h, void *); /**< This callback function is called when other application send the launch request to the application. */ + int (*pause) (void *); /**< Called when every window goes back */ + int (*resume) (void *); /**< Called when any window comes on top */ + int (*terminate) (void *); /**< This callback function is called once after the main loop of application exits. */ + void (*time_tick) (void *, void *); + void (*ambient_tick) (void *, void *); + void (*ambient_changed) (int, void *); + + void *reserved[6]; + /**< Reserved */ +}; + +enum watch_core_event { + /**< Unknown event */ + WATCH_CORE_EVENT_UNKNOWN, + + /**< Low memory */ + WATCH_CORE_EVENT_LOW_MEMORY, + + /**< Low battery */ + WATCH_CORE_EVENT_LOW_BATTERY, + + /**< Language setting is changed */ + WATCH_CORE_EVENT_LANG_CHANGE, + + /**< Region setting is changed */ + WATCH_CORE_EVENT_REGION_CHANGE, +}; + +struct watch_time_s +{ + int year; + int month; + int day_of_week; + int day; + int hour; + int hour24; + int minute; + int second; + int millisecond; + time_t timestamp; + char *timezone; +}; + +int watch_core_main(const char *appid, int argc, char **argv, struct watchcore_ops *ops); + +int watch_core_terminate(); + +int watch_core_set_event_callback(enum watch_core_event event, + int (*cb)(void *, void *), void *data); + + +void watch_core_get_timeinfo(struct watch_time_s *timeinfo); + +bool watch_core_get_24h_mode(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __APPCORE_WATCH_H__ */ diff --git a/include/watch_app.h b/include/watch_app.h new file mode 100755 index 0000000..d7e8b88 --- /dev/null +++ b/include/watch_app.h @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +#ifndef __TIZEN_APPFW_WATCH_APP_H__ +#define __TIZEN_APPFW_WATCH_APP_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup CAPI_WATCH_APP_MODULE + * @{ + */ + +/** + * @brief watch_time_h watch_time handle + * @since_tizen 2.3.1 + */ +typedef struct _watch_time_s* watch_time_h; + +/** + * @brief Called when the application starts. + * @since_tizen 2.3.1 + * + * @details The callback function is called before the main loop of the application starts. + * In this callback, you can initialize application resources like window creation, data structure, and so on. + * After this callback function returns @c true, the main loop starts up and watch_app_control_cb() is subsequently called. + * If this callback function returns @c false, the main loop doesn't start and watch_app_terminate_cb() is subsequently called. + * + * @param[in] width The width of the window of idle screen that will show the watch UI + * @param[in] height The height of the window of idle screen that will show the watch UI + * @param[in] user_data The user data passed from the callback registration function + * @return @c true on success, + * otherwise @c false + * @see watch_app_main() + * @see #watch_app_lifecycle_callback_s + */ +typedef bool (*watch_app_create_cb) (int width, int height, void *user_data); + +/** + * @brief Called when another application sends a launch request to the application. + * @since_tizen 2.3.1 + * + * @details When the application is launched, this callback function is called after the main loop of the application starts up. + * The passed app_control handle describes the launch request and contains the information about why the application is launched. + * If the launch request is sent to the application in the running or pause state, + * this callback function can be called again to notify that the application has been asked to launch. + * + * The application is responsible for handling each launch request and responding appropriately. + * Using the App Control API, the application can get information about what is to be performed. + * The app_control handle may include only the default operation (#APP_CONTROL_OPERATION_DEFAULT) without any data. + * For more information, see The @ref CAPI_APP_CONTROL_MODULE API description. + * + * @param[in] app_control The handle to the app_control + * @param[in] user_data The user data passed from the callback registration function + * @see watch_app_main() + * @see #watch_app_lifecycle_callback_s + * @see @ref CAPI_APP_CONTROL_MODULE API + */ +typedef void (*watch_app_control_cb) (app_control_h app_control, void *user_data); + +/** + * @brief Called when the application is completely obscured by another application and becomes invisible. + * @since_tizen 2.3.1 + * + * @details The application is not terminated and still running in the paused state. + * + * @param[in] user_data The user data passed from the callback registration function + * @see watch_app_main() + * @see #watch_app_lifecycle_callback_s + */ +typedef void (*watch_app_pause_cb) (void *user_data); + +/** + * @brief Called when the application becomes visible. + * @since_tizen 2.3.1 + * + * @remarks This callback function is not called when the application moves from the created state to the running state. + * + * @param[in] user_data The user data passed from the callback registration function + * @see watch_app_main() + * @see #watch_app_lifecycle_callback_s + */ +typedef void (*watch_app_resume_cb) (void *user_data); + +/** + * @brief Called when the application's main loop exits. + * @details You should release the application's resources in this function. + * @since_tizen 2.3.1 + * + * @param[in] user_data The user data passed from the callback registration function + * @see watch_app_main() + * @see #watch_app_lifecycle_callback_s + */ +typedef void (*watch_app_terminate_cb) (void *user_data); + +/** + * @brief Called at each second. This callback is not called while the app is paused or the device is in ambient mode. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch time handle. watch_time will not be available after returning this callback. It will be freed by the framework. + * @param[in] user_data The user data to be passed to the callback functions + */ +typedef void (*watch_app_time_tick_cb) (watch_time_h watch_time, void *user_data); + +/** + * @brief Called at each minute when the device in the ambient mode. + * @since_tizen 2.3.1 + * + * @remarks You should not do a job that takes long time in this callback. You should update the UI as fast as possible in this callback. The platform might make the device to sleep in short time after the ambient tick expires. + * + * @param[in] watch_time The watch time handle. watch_time will not be available after returning this callback. It will be freed by the framework. + * @param[in] user_data The user data to be passed to the callback functions + */ +typedef void (*watch_app_ambient_tick_cb) (watch_time_h watch_time, void *user_data); + +/** + * @brief Called when the device enters or exits the ambient mode. + * @since_tizen 2.3.1 + * + * @remarks For low powered wearable device, Tizen watch application supports a special mode that is named 'ambient'. When the device enters ambient mode, Tizen watch application that is shown in the idle screen can show limited UI and receives only ambient tick event at each minute to reduce power consumption. The limitation of UI that can be drawn in the ambient mode depends on the device. Usually, you should draw black and white UI only, and you should use below 20% of the pixels of the screen. If you don't want to draw your own ambient mode UI, you can set the 'ambient-support' attribute of the application as 'false' in the tizen-manifest.xml. Then, the platform will show proper default ambient mode UI. + * + * @param[in] ambient_mode If @c true the device enters the ambient mode, + * otherwise @c false + * @param[in] user_data The user data to be passed to the callback functions + */ +typedef void (*watch_app_ambient_changed_cb) (bool ambient_mode, void *user_data); + + +/** + * @brief The structure type containing the set of callback functions for handling application events. + * @details It is one of the input parameters of the watch_app_main() function. + * @since_tizen 2.3.1 + * + * @see watch_app_main() + * @see watch_app_create_cb() + * @see watch_app_control_cb() + * @see watch_app_pause_cb() + * @see watch_app_resume_cb() + * @see watch_app_time_tick_cb() + * @see watch_app_ambient_tick_cb() + * @see watch_app_ambient_changed_cb() + * @see watch_app_terminate_cb() + */ +typedef struct +{ + watch_app_create_cb create; /**< This callback function is called at the start of the application. */ + watch_app_control_cb app_control; /**< This callback function is called when another application sends the launch request to the application. */ + watch_app_pause_cb pause; /**< This callback function is called each time the application is completely obscured by another application and becomes invisible to the user. */ + watch_app_resume_cb resume; /**< This callback function is called each time the application becomes visible to the user. */ + watch_app_terminate_cb terminate; /**< This callback function is called before the application exits. */ + watch_app_time_tick_cb time_tick; /**< This callback function is called at each second. */ + watch_app_ambient_tick_cb ambient_tick; /**< This callback function is called at each minute in ambient mode. */ + watch_app_ambient_changed_cb ambient_changed; /**< This callback function is called when the device enters or exits ambient mode. */ + +} watch_app_lifecycle_callback_s; + + +/** + * @brief Adds the system event handler + * @since_tizen 2.3.1 + * + * @param[out] handler The event handler + * @param[in] event_type The system event type + * @param[in] callback The callback function + * @param[in] user_data The user data to be passed to the callback function + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_NONE Successfull + * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #APP_ERROR_OUT_OF_MEMORY Out of memory + * + * @see app_event_type_e + * @see app_event_cb + * @see watch_app_remove_event_handler + */ +int watch_app_add_event_handler(app_event_handler_h *handler, app_event_type_e event_type, app_event_cb callback, void *user_data); + + +/** + * @brief Removes registered event handler + * @since_tizen 2.3.1 + * + * @param[in] event_handler The event handler + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_NONE Successfull + * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter + * + * @see watch_app_add_event_handler + */ +int watch_app_remove_event_handler(app_event_handler_h event_handler); + + +/** + * @brief Runs the main loop of the application until watch_app_exit() is called. + * @since_tizen 2.3.1 + * + * @remarks http://tizen.org/privilege/alarm.set privilege is needed to receive ambient ticks at each minute. If your app hasn't the privilege and you set the watch_app_ambient_tick_cb(), #APP_ERROR_PERMISSION_DENIED will be returned. + * + * @param[in] argc The argument count + * @param[in] argv The argument vector + * @param[in] callback The set of callback functions to handle application events + * @param[in] user_data The user data to be passed to the callback functions + * + * @return @c 0 on success, + * otherwise a negative error value. + * @retval #APP_ERROR_NONE Successful + * @retval #APP_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #APP_ERROR_INVALID_CONTEXT The application is illegally launched, not launched by the launch system. + * @retval #APP_ERROR_ALREADY_RUNNING The main loop has already started + * @retval #APP_ERROR_PERMISSION_DENIED Permission denied + * + * @see watch_app_main() + * @see watch_app_create_cb() + * @see watch_app_control_cb() + * @see watch_app_pause_cb() + * @see watch_app_resume_cb() + * @see watch_app_time_tick_cb() + * @see watch_app_ambient_tick_cb() + * @see watch_app_ambient_changed_cb() + * @see watch_app_terminate_cb() + * @see #watch_app_lifecycle_callback_s + */ +int watch_app_main(int argc, char **argv, watch_app_lifecycle_callback_s *callback, void *user_data); + + +/** + * @brief Exits the main loop of the application. + * @details The main loop of the application stops and watch_app_terminate_cb() is invoked. + * @since_tizen 2.3.1 + * + * @see watch_app_main() + * @see watch_app_terminate_cb() + */ +void watch_app_exit(void); + +/** + * @brief Gets the current time. + * @since_tizen 2.3.1 + * + * @remarks You must release @a watch_time using watch_time_delete() after using it. + * + * @param[out] watch_time The watch_time handle to be newly created on successl + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_OUT_OF_MEMORY Out of Memory + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_current_time(watch_time_h* watch_time); + +/** + * @brief Deletes the watch time handle and releases all its resources. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_delete(watch_time_h watch_time); + +/** + * @brief Gets the year info. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] year The year info + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_year(watch_time_h watch_time, int *year); + +/** + * @brief Gets the month info. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] month The month info + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_month(watch_time_h watch_time, int *month); + +/** + * @brief Gets the day info. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] day The day info + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_day(watch_time_h watch_time, int *day); + +/** + * @brief Gets the day of week info. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] day_of_week The day of week info. The value returns from 1 (Sunday) to 7 (Saturday). + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_day_of_week(watch_time_h watch_time, int *day_of_week); + +/** + * @brief Gets the hour info. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] hour The hour info + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_hour(watch_time_h watch_time, int *hour); + +/** + * @brief Gets the hour info in 24-hour presentation. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] hour24 The hour info + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_hour24(watch_time_h watch_time, int *hour24); + +/** + * @brief Gets the minute info. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] minute The minute info + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_minute(watch_time_h watch_time, int *minute); + +/** + * @brief Gets the second info. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] second The second info + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_second(watch_time_h watch_time, int *second); + +/** + * @brief Gets the millisecond info. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] millisecond The millisecond info + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_millisecond(watch_time_h watch_time, int *millisecond); + +/** + * @brief Gets the UTC time. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] utc_time The UTC time + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_utc_time(watch_time_h watch_time, struct tm *utc_time); + +/** + * @brief Gets the UTC timestamp. + * @since_tizen 2.3.1 + * + * @param[in] watch_time The watch_time handle + * @param[out] utc_timestamp The UTC timestamp + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_utc_timestamp(watch_time_h watch_time, time_t *utc_timestamp); + +/** + * @brief Gets the ID of timezone for the @a watch_time handle. + * @since_tizen 2.3.1 + * + * @remarks You must release @a time_zone_id using free() after using it. + * + * @param[in] watch_time The watch_time handle + * @param[out] time_zone_id The Timezone ID, such as "America/Los_Angeles" + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_NONE Successful + */ +int watch_time_get_time_zone(watch_time_h watch_time, char **time_zone_id); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_APPFW_WATCH_APP_H__ */ diff --git a/include/watch_app_efl.h b/include/watch_app_efl.h new file mode 100644 index 0000000..f4863a6 --- /dev/null +++ b/include/watch_app_efl.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#ifndef __TIZEN_APPFW_WATCH_APP_EFL_H__ +#define __TIZEN_APPFW_WATCH_APP_EFL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @addtogroup CAPI_WATCH_APP_MODULE + * @{ + */ + +/** + * @brief Gets Evas_Object for a Elementary window of watch application. You must use this window to draw watch UI on the idle screen. + * @since_tizen 2.3.1 + * + * @param[out] win The pointer of Evas_Object for a Elementary window. + * + * @return 0 on success, otherwise a negative error value + * @retval #APP_ERROR_INVALID_PARAMETER Invalid Parameter + * @retval #APP_ERROR_OUT_OF_MEMORY Out of memory + * @retval #APP_ERROR_INVALID_CONTEXT Watch app is not initialized properly + * @retval #APP_ERROR_NONE Successful + */ +int watch_app_get_elm_win(Evas_Object **win); + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/packaging/appcore-watch.spec b/packaging/appcore-watch.spec new file mode 100644 index 0000000..accd33a --- /dev/null +++ b/packaging/appcore-watch.spec @@ -0,0 +1,87 @@ +Name: appcore-watch +Summary: Watch Application +Version: 1.2.3.1 +Release: 3 +Group: Application Framework/Libraries +License: Apache-2.0 +Source0: appcore-watch-%{version}.tar.gz +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(elementary) +BuildRequires: pkgconfig(dbus-glib-1) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(vconf-internal-keys) +BuildRequires: pkgconfig(alarm-service) +BuildRequires: pkgconfig(widget_provider_app) +BuildRequires: pkgconfig(widget) +BuildRequires: pkgconfig(capi-appfw-app-control) +BuildRequires: pkgconfig(capi-appfw-app-common) +BuildRequires: cmake + + +%description +Watch application + + +%package devel +Summary: appcore watch +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +%description devel +appcore watch (developement files) + +%package -n capi-appfw-watch-application-devel +Summary: watch appliation +Group: Development/Libraries +Requires: appcore-watch-devel = %{version}-%{release} +%description -n capi-appfw-watch-application-devel +watch application (developement files) + +%prep +%setup -q + + +%build +%if 0%{?sec_build_binary_debug_enable} +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" +%endif +export CFLAGS="$CFLAGS -Wall -Werror -Wno-unused-function -Wno-unused-but-set-variable" +CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" cmake . -DCMAKE_INSTALL_PREFIX=/usr + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}/usr/lib/pkgconfig +cp capi-appfw-watch-application.pc %{buildroot}/usr/lib/pkgconfig +mkdir -p %{buildroot}/usr/share/license +cp LICENSE %{buildroot}/usr/share/license/%{name} + + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + + +%files +%manifest appcore-watch.manifest +%defattr(-,root,root,-) +/usr/lib/libappcore-watch.so +/usr/lib/libappcore-watch.so.1 +/usr/lib/libappcore-watch.so.1.1 +/usr/share/license/%{name} + +%files devel +%defattr(-,root,root,-) +/usr/lib/pkgconfig/appcore-watch.pc +/usr/include/appcore-watch/appcore-watch.h + +%files -n capi-appfw-watch-application-devel +/usr/include/appcore-watch/watch_app.h +/usr/include/appcore-watch/watch_app_efl.h +/usr/lib/pkgconfig/capi-appfw-watch-application.pc + diff --git a/src/appcore-watch-i18n.c b/src/appcore-watch-i18n.c new file mode 100755 index 0000000..9fd2e44 --- /dev/null +++ b/src/appcore-watch-i18n.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "appcore-watch-log.h" +#include "appcore-watch-internal.h" + +#define BASE_LANG "en_GB.UTF-8" +#define CSC_DEFAULT_INI "/opt/system/csc-default/data/csc-default-data.ini" + +#define PKGNAME_MAX 256 +#define PATH_APP_ROOT "/opt/usr/apps" +#define PATH_RO_APP_ROOT "/usr/apps" +#define PATH_RES "/res" +#define PATH_LOCALE "/locale" + +void _update_lang(void) +{ + char *lang = vconf_get_str(VCONFKEY_LANGSET); + if (lang) { + setenv("LANG", lang, 1); + setenv("LC_MESSAGES", lang, 1); + + char *r = setlocale(LC_ALL, ""); + if (r == NULL) { + r = setlocale(LC_ALL, lang); + if (r) { + _D("*****appcore setlocale=%s\n", r); + } + } + free(lang); + } else { + _E("failed to get current language for set lang env"); + } +} + +void _update_region(void) +{ + char *region; + char *r; + + region = vconf_get_str(VCONFKEY_REGIONFORMAT); + if (region) { + setenv("LC_CTYPE", region, 1); + setenv("LC_NUMERIC", region, 1); + setenv("LC_TIME", region, 1); + setenv("LC_COLLATE", region, 1); + setenv("LC_MONETARY", region, 1); + setenv("LC_PAPER", region, 1); + setenv("LC_NAME", region, 1); + setenv("LC_ADDRESS", region, 1); + setenv("LC_TELEPHONE", region, 1); + setenv("LC_MEASUREMENT", region, 1); + setenv("LC_IDENTIFICATION", region, 1); + r = setlocale(LC_ALL, ""); + if (r != NULL) { + _D("*****appcore setlocale=%s\n", r); + } + free(region); + } else { + _E("failed to get current region format for set region env"); + } +} + +static int __get_dir_name(char *dirname) +{ + char pkgid[PKGNAME_MAX]; + int r; + int pid; + char cmdline[PATH_MAX]; + char *name = NULL; + int len = 0; + + pid = getpid(); + if (pid < 0) + return -1; + + r = aul_app_get_cmdline_bypid(pid, cmdline, PATH_MAX); + if (r != 0) { + _E("failed to get cmdline"); + return -1; + } + + //Legacy code that will be removed. + if (strncmp(cmdline, PATH_APP_ROOT, strlen(PATH_APP_ROOT)) != 0 + && strncmp(cmdline, PATH_RO_APP_ROOT, strlen(PATH_RO_APP_ROOT)) != 0) { + + if (aul_app_get_pkgid_bypid(pid, pkgid, PKGNAME_MAX) != AUL_R_OK) + return -1; + + r = snprintf(dirname, PATH_MAX, PATH_APP_ROOT "/%s" PATH_RES PATH_LOCALE, pkgid); + if (r < 0) + return -1; + + if (access(dirname, R_OK) == 0) + return 0; + + r = snprintf(dirname, PATH_MAX, PATH_RO_APP_ROOT "/%s" PATH_RES PATH_LOCALE, pkgid); + if (r < 0) + return -1; + } + else { + name = (char *)g_strrstr(cmdline, "/"); + if (name) + name[0] = '\0'; + name = (char *)g_strrstr(cmdline, "/"); + if (name) + name[0] = '\0'; + + len = strlen(cmdline); + strncpy(dirname, cmdline, len); + dirname[len] = '\0'; + + strcat(dirname, "/res/locale"); + } + + return 0; +} + + +static int __set_i18n(const char *domain) +{ + char *r; + char dirname[PATH_MAX]; + + if (domain == NULL) { + errno = EINVAL; + return -1; + } + + __get_dir_name(dirname); + _D("locale dir: %s", dirname); + + r = setlocale(LC_ALL, ""); + /* if locale is not set properly, try again to set as language base */ + if (r == NULL) { + char *lang = vconf_get_str(VCONFKEY_LANGSET); + r = setlocale(LC_ALL, lang); + if (r) { + _D("*****appcore setlocale=%s\n", r); + } + if (lang) { + free(lang); + } + } + if (r == NULL) { + _E("appcore: setlocale() error"); + } + + r = bindtextdomain(domain, dirname); + if (r == NULL) { + _E("appcore: bindtextdomain() error"); + } + + r = textdomain(domain); + if (r == NULL) { + _E("appcore: textdomain() error"); + } + + return 0; +} + +int _set_i18n(const char *domainname) +{ + _update_lang(); + _update_region(); + + return __set_i18n(domainname); +} + diff --git a/src/appcore-watch-internal.h b/src/appcore-watch-internal.h new file mode 100644 index 0000000..3ae04ea --- /dev/null +++ b/src/appcore-watch-internal.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +#ifndef __APPCORE_WATCH_INTERNAL_H__ +#define __APPCORE_WATCH_INTERNAL_H__ + +int _set_i18n(const char *domainname); +void _update_lang(void); +void _update_region(void); + +#endif /* __APPCORE_WATCH_INTERNAL_H__ */ diff --git a/src/appcore-watch-log.h b/src/appcore-watch-log.h new file mode 100755 index 0000000..49f0d8f --- /dev/null +++ b/src/appcore-watch-log.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +#ifndef __APPFW_WATCH_LOG_H__ +#define __APPFW_WATCH_LOG_H__ + +#include + +#define _E(fmt, arg...) LOGE(fmt, ##arg) +#define _I(fmt, arg...) LOGI(fmt, ##arg) +#define _D(fmt, arg...) LOGD(fmt, ##arg) +#define _W(fmt, arg...) LOGW(fmt, ##arg) + +#ifndef EXPORT_API +#define EXPORT_API __attribute__ ((visibility("default"))) +#endif + +#ifndef _E +#define _E(fmt, arg...) LOGE(fmt, ##arg) +#endif + +#ifndef _I +#define _I(...) LOGI(__VA_ARGS__) +#endif + +#ifndef _D +#define _D(...) LOGD(__VA_ARGS__) +#endif + +#ifndef _W +#define _W(...) LOGW(__VA_ARGS__) +#endif + +#define _warn_if(expr, fmt, arg...) do { \ + if (expr) { \ + _ERR(fmt, ##arg); \ + } \ + } while (0) + +#define _ret_if(expr) do { \ + if (expr) { \ + return; \ + } \ + } while (0) + +#define _retv_if(expr, val) do { \ + if (expr) { \ + return (val); \ + } \ + } while (0) + +#define _retm_if(expr, fmt, arg...) do { \ + if (expr) { \ + _ERR(fmt, ##arg); \ + return; \ + } \ + } while (0) + +#define _retvm_if(expr, val, fmt, arg...) do { \ + if (expr) { \ + _ERR(fmt, ##arg); \ + return (val); \ + } \ + } while (0) + + +#endif //__APPFW_WATCH_LOG_H_ diff --git a/src/appcore-watch-signal.c b/src/appcore-watch-signal.c new file mode 100755 index 0000000..0f4eea4 --- /dev/null +++ b/src/appcore-watch-signal.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + + + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "appcore-watch-log.h" +#include "appcore-watch-signal.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "WATCH_CORE" + + +#define MAX_BUFFER_SIZE 512 + +static DBusConnection *bus = NULL; + +static int (*_deviced_signal_alpm_handler) (int ambient, void *data); +static void *_deviced_signal_alpm_data; + +static DBusHandlerResult +__dbus_signal_filter(DBusConnection *conn, DBusMessage *message, + void *user_data) +{ + const char *sender; + const char *interface; + const char *value; + + DBusError error; + dbus_error_init(&error); + + sender = dbus_message_get_sender(message); + if (sender == NULL) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + interface = dbus_message_get_interface(message); + if (interface == NULL) { + _E("reject by security issue - no interface\n"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + if (dbus_message_is_signal(message, interface, DEVICED_SIGNAL_HOME_SCREEN)) + { + if (dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &value, DBUS_TYPE_INVALID) == FALSE) { + _E("Failed to get data: %s", error.message); + dbus_error_free(&error); + } + + if (_deviced_signal_alpm_handler) + { + if (strcmp(value, CLOCK_START) == 0) + { + _deviced_signal_alpm_handler(1, _deviced_signal_alpm_data); + } + else if (strcmp(value, CLOCK_STOP) == 0) + { + _deviced_signal_alpm_handler(0, _deviced_signal_alpm_data); + } + } + } + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static int __dbus_init(void) +{ + if (bus) + return 0; + + DBusError error; + dbus_error_init(&error); + bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); + if (!bus) { + _E("Failed to connect to the D-BUS daemon: %s", error.message); + dbus_error_free(&error); + return -1; + } + + dbus_connection_setup_with_g_main(bus, NULL); + + return 0; +} + +static int __dbus_signal_handler_init(const char* path, const char* interface) +{ + char rule[MAX_BUFFER_SIZE] = {0,}; + + DBusError error; + dbus_error_init(&error); + + snprintf(rule, MAX_BUFFER_SIZE, + "path='%s',type='signal',interface='%s'", path, interface); + + dbus_bus_add_match(bus, rule, &error); + if (dbus_error_is_set(&error)) { + _E("Fail to rule set: %s", error.message); + dbus_error_free(&error); + return -1; + } + + if (dbus_connection_add_filter(bus, __dbus_signal_filter, NULL, NULL) == FALSE) { + _E("add filter fail"); + return -1; + } + + return 0; +} + +int _watch_core_listen_alpm_handler(int (*func) (int, void *), void *data) +{ + _D("watch_core_listen_deviced_alpm"); + + __dbus_init(); + + if(__dbus_signal_handler_init(DEVICED_PATH, DEVICED_INTERFACE) < 0) + { + _E("error app signal init"); + return -1; + } + + _deviced_signal_alpm_handler = func; + _deviced_signal_alpm_data = data; + + return 0; +} + +int _watch_core_send_alpm_update_done(void) +{ + DBusMessage *message; + + __dbus_init(); + + message = dbus_message_new_signal(ALPM_VIEWER_PATH, + ALPM_VIEWER_INTERFACE, + ALPM_VIEWER_SIGNAL_DRAW_DONE); + + if (dbus_message_append_args(message, + DBUS_TYPE_INVALID) == FALSE) { + _E("Failed to load data error"); + return -1; + } + + if (dbus_connection_send(bus, message, NULL) == FALSE) { + _E("dbus send error"); + return -1; + } + + dbus_connection_flush(bus); + dbus_message_unref(message); + + _I("send a alpm update done signal"); + + return 0; +} + diff --git a/src/appcore-watch-signal.h b/src/appcore-watch-signal.h new file mode 100755 index 0000000..6a35b47 --- /dev/null +++ b/src/appcore-watch-signal.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +#ifndef __APPCORE_WATCH_SIGNAL_H__ +#define __APPCORE_WATCH_SIGNAL_H__ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ALPM_VIEWER_PATH "/Org/Tizen/Coreapps/Alpmviewer/Clockdraw" +#define ALPM_VIEWER_INTERFACE "org.tizen.coreapps.alpmviewer.clockdraw" +#define ALPM_VIEWER_SIGNAL_DRAW_DONE "drawdone" + + +#define DEVICED_PATH "/Org/Tizen/System/DeviceD" +#define DEVICED_INTERFACE "org.tizen.system.deviced" +#define DEVICED_SIGNAL_HOME_SCREEN "HomeScreen" +#define CLOCK_START "clockbegin" +#define CLOCK_STOP "clockstop" + +int _watch_core_listen_alpm_handler(int (*func) (int, void *), void *data); +int _watch_core_send_alpm_update_done(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __APPCORE_WATCH_SIGNAL_H__ */ diff --git a/src/appcore-watch.c b/src/appcore-watch.c new file mode 100755 index 0000000..4444be0 --- /dev/null +++ b/src/appcore-watch.c @@ -0,0 +1,1111 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include "appcore-watch.h" +#include "appcore-watch-log.h" +#include "appcore-watch-signal.h" +#include "appcore-watch-internal.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "WATCH_CORE" + +#include +#include +#include +#include +#include +#include + +#define WATCH_ID "internal://WATCH_ID" + +#define AUL_K_CALLER_APPID "__AUL_CALLER_APPID__" +#define APPID_BUFFER_MAX 255 + +#define TIMEZONE_BUFFER_MAX 1024 +#define LOCAL_TIME_PATH "/opt/etc/localtime" + +#define ONE_SECOND 1000 +#define ONE_MINUTE 60 +#define ONE_HOUR 60 + +static Ecore_Timer *watch_tick = NULL; + +static alarm_id_t alarm_id = 0; + +/** + * Appcore internal system event + */ +enum sys_event { + SE_UNKNOWN, + SE_LOWMEM, + SE_LOWBAT, + SE_LANGCHG, + SE_REGIONCHG, + SE_MAX +}; + +/** + * watch internal state + */ +enum watch_state { + WS_NONE, + WS_CREATED, + WS_RUNNING, + WS_PAUSED, + WS_DYING, +}; + +enum watch_event { + WE_UNKNOWN, + WE_CREATE, + WE_PAUSE, + WE_RESUME, + WE_APPCONTROL, + WE_AMBIENT, + WE_TERMINATE, + WE_MAX +}; + + +static enum watch_core_event to_ae[SE_MAX] = { + WATCH_CORE_EVENT_UNKNOWN, /* SE_UNKNOWN */ + WATCH_CORE_EVENT_LOW_MEMORY, /* SE_LOWMEM */ + WATCH_CORE_EVENT_LOW_BATTERY, /* SE_LOWBAT */ + WATCH_CORE_EVENT_LANG_CHANGE, + WATCH_CORE_EVENT_REGION_CHANGE, +}; + + +enum cb_type { /* callback */ + _CB_NONE, + _CB_SYSNOTI, + _CB_APPNOTI, + _CB_VCONF, +}; + +struct evt_ops { + enum cb_type type; + union { + enum watch_core_event sys; + enum watch_event app; + const char *vkey; + } key; + + int (*cb_pre) (void *); + int (*cb) (void *); + int (*cb_post) (void *); + + int (*vcb_pre) (void *, void *); + int (*vcb) (void *, void *); + int (*vcb_post) (void *, void *); +}; + +struct watch_priv { + const char *appid; + const char *name; + pid_t pid; + enum watch_state state; + int ambient_mode; + int ambient_mode_skip_resume; + + struct watchcore_ops *ops; +}; + +static struct watch_priv priv; + +struct watch_ops { + void *data; + void (*cb_app)(enum watch_event, void *, bundle *); +}; + +/** + * Appcore system event operation + */ +struct sys_op { + int (*func) (void *, void *); + void *data; +}; + +struct watch_core { + int init; + + const struct watch_ops *ops; + struct sys_op sops[SE_MAX]; +}; + +static struct watch_core core; + +static int __sys_lowmem_post(void *data, void *evt); +static int __sys_lowmem(void *data, void *evt); +static int __sys_lowbatt(void *data, void *evt); +static int __sys_langchg_pre(void *data, void *evt); +static int __sys_langchg(void *data, void *evt); +static int __sys_regionchg_pre(void *data, void *evt); +static int __sys_regionchg(void *data, void *evt); + + +static struct evt_ops evtops[] = { + { + .type = _CB_VCONF, + .key.vkey = VCONFKEY_SYSMAN_LOW_MEMORY, + .vcb_post = __sys_lowmem_post, + .vcb = __sys_lowmem, + }, + { + .type = _CB_VCONF, + .key.vkey = VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, + .vcb = __sys_lowbatt, + }, + { + .type = _CB_VCONF, + .key.vkey = VCONFKEY_LANGSET, + .vcb_pre = __sys_langchg_pre, + .vcb = __sys_langchg, + }, + { + .type = _CB_VCONF, + .key.vkey = VCONFKEY_REGIONFORMAT, + .vcb_pre = __sys_regionchg_pre, + .vcb = __sys_regionchg, + }, +}; + +static void __watch_core_signal_init(void); +static int __watch_core_widget_init(void); + +static Eina_Bool __watch_core_time_tick(void *data); +static void __watch_core_time_tick_cancel(void); + +static int __watch_core_ambient_tick(alarm_id_t id, void *data); + +static int __widget_create(const char *id, const char *content, int w, int h, void *data); +static int __widget_resize(const char *id, int w, int h, void *data); +static int __widget_destroy(const char *id, widget_destroy_type_e reason, void *data); +static int __widget_pause(const char *id, void *data); +static int __widget_resume(const char *id, void *data); + +struct widget_provider_event_callback widget_ops = { + .create = __widget_create, + .resize = __widget_resize, + .destroy = __widget_destroy, + .update = NULL, + .text_signal = NULL, + + .pause = __widget_pause, + .resume = __widget_resume, + + .connected = NULL, + .disconnected = NULL, + .data = NULL, +}; + +extern int app_control_create_event(bundle *data, struct app_control_s **app_control); + +static void __exit_loop(void *data) +{ + ecore_main_loop_quit(); +} + +static void __do_app(enum watch_event event, void *data, bundle * b) +{ + struct watch_priv *watch_data = data; + app_control_h app_control = NULL; + + _ret_if(watch_data == NULL); + + if (event == WE_TERMINATE) + { + watch_data->state = WS_DYING; + ecore_main_loop_thread_safe_call_sync((Ecore_Data_Cb)__exit_loop, NULL); + return; + } + + _ret_if(watch_data->ops == NULL); + + switch (event) + { + case WE_APPCONTROL: + _D("appcontrol request"); + + if (app_control_create_event(b, &app_control) != 0) + { + _E("failed to get the app_control handle"); + return; + } + + if (!widget_provider_app_is_initialized()) + { + _D("widget is not initialized"); + assert(0); + } + else + { + _D("widget is initialized"); + + if (watch_data->ops->app_control) + watch_data->ops->app_control(app_control, watch_data->ops->data); + } + + app_control_destroy(app_control); + + break; + + case WE_PAUSE: + _D("WE_PAUSE"); + + if (watch_data->state == WS_CREATED) + { + _E("Invalid state"); + + return; + } + + // Handling the ambient mode + if (watch_data->ambient_mode) + { + watch_data->ambient_mode_skip_resume = 1; + } + + // Cancel the time_tick callback + __watch_core_time_tick_cancel(); + + if (watch_data->state == WS_RUNNING) + { + + if (watch_data->ops->pause) { + int r = priv.ops->pause(priv.ops->data); + if (r < 0) { + _E("pause() fails"); + } + } + } + + watch_data->state = WS_PAUSED; + break; + + case WE_RESUME: + _D("WE_RESUME"); + + // Handling the ambient mode + if (watch_data->ambient_mode) + { + watch_data->ambient_mode_skip_resume = 0; + return; + } + + if (watch_data->state == WS_PAUSED || watch_data->state == WS_CREATED) + { + if (watch_data->ops->resume) { + int r = priv.ops->resume(priv.ops->data); + if (r < 0) { + _E("resume() fails"); + } + } + } + + watch_data->state = WS_RUNNING; + + // Set the time tick callback + if (!watch_tick) + { + __watch_core_time_tick(NULL); + } + else + { + __watch_core_time_tick_cancel(); + __watch_core_time_tick(NULL); + } + + break; + + case WE_AMBIENT: + _D("WE_AMBIENT"); + + if (priv.ops && priv.ops->ambient_changed) { + priv.ops->ambient_changed(watch_data->ambient_mode, priv.ops->data); + } + + break; + + default: + break; + } + +} + +static struct watch_ops w_ops = { + .data = &priv, + .cb_app = __do_app, +}; + +char* __get_domain_name(const char *appid) +{ + char *name_token = NULL; + + if (appid == NULL) + { + _E("appid is NULL"); + return NULL; + } + + // com.vendor.name -> name + name_token = strrchr(appid, '.'); + + if (name_token == NULL) + { + _E("appid is invalid"); + return NULL; + } + + name_token++; + + return strdup(name_token); +} + +static int __set_data(struct watch_priv *watch, const char *appid, struct watchcore_ops *ops) +{ + if (ops == NULL) { + errno = EINVAL; + return -1; + } + + watch->ops = ops; + + watch->appid = strdup(appid); + watch->name = __get_domain_name(appid); + watch->pid = getpid(); + + return 0; +} + +static int __watch_appcontrol(void *data, bundle * k) +{ + struct watch_core *wc = data; + _retv_if(wc == NULL || wc->ops == NULL, -1); + _retv_if(wc->ops->cb_app == NULL, 0); + + wc->ops->cb_app(WE_APPCONTROL, wc->ops->data, k); + + return 0; +} + +static int __watch_terminate(void *data) +{ + struct watch_core *wc = data; + + _retv_if(wc == NULL || wc->ops == NULL, -1); + _retv_if(wc->ops->cb_app == NULL, 0); + + wc->ops->cb_app(WE_TERMINATE, wc->ops->data, NULL); + + return 0; +} + +static int __sys_do_default(struct watch_core *wc, enum sys_event event) +{ + int r; + + switch (event) { + case SE_LOWBAT: + /*r = __def_lowbatt(wc);*/ + r = 0; + break; + default: + r = 0; + break; + }; + + return r; +} + +static int __sys_do(struct watch_core *wc, void *event_info, enum sys_event event) +{ + struct sys_op *op; + + _retv_if(wc == NULL || event >= SE_MAX, -1); + + op = &wc->sops[event]; + + if (op->func == NULL) + return __sys_do_default(wc, event); + + return op->func(event_info, op->data); +} + +static int __sys_lowmem_post(void *data, void *evt) +{ + keynode_t *key = evt; + int val; + + val = vconf_keynode_get_int(key); + + if (val == VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) { +#if defined(MEMORY_FLUSH_ACTIVATE) + struct appcore *wc = data; + wc->ops->cb_app(AE_LOWMEM_POST, wc->ops->data, NULL); +#else + malloc_trim(0); +#endif + } + return 0; +} + +static int __sys_lowmem(void *data, void *evt) +{ + keynode_t *key = evt; + int val; + + val = vconf_keynode_get_int(key); + + if (val == VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) + return __sys_do(data, (void *)&val, SE_LOWMEM); + + return 0; +} + +static int __sys_lowbatt(void *data, void *evt) +{ + keynode_t *key = evt; + int val; + + val = vconf_keynode_get_int(key); + + /* VCONFKEY_SYSMAN_BAT_CRITICAL_LOW or VCONFKEY_SYSMAN_POWER_OFF */ + if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW) + return __sys_do(data, (void *)&val, SE_LOWBAT); + + return 0; +} + +static int __sys_langchg_pre(void *data, void *evt) +{ + _update_lang(); + return 0; +} + +static int __sys_langchg(void *data, void *evt) +{ + keynode_t *key = evt; + char *val; + + val = vconf_keynode_get_str(key); + + return __sys_do(data, (void *)val, SE_LANGCHG); +} + +static int __sys_regionchg_pre(void *data, void *evt) +{ + _update_region(); + return 0; +} + +static int __sys_regionchg(void *data, void *evt) +{ + keynode_t *key = evt; + char *val; + + val = vconf_keynode_get_str(key); + + return __sys_do(data, (void *)val, SE_REGIONCHG); +} + +static void __vconf_do(struct evt_ops *eo, keynode_t * key, void *data) +{ + _ret_if(eo == NULL); + + if (eo->vcb_pre) + eo->vcb_pre(data, key); + + if (eo->vcb) + eo->vcb(data, key); + + if (eo->vcb_post) + eo->vcb_post(data, key); +} + +static void __vconf_cb(keynode_t *key, void *data) +{ + int i; + const char *name; + + name = vconf_keynode_get_name(key); + _ret_if(name == NULL); + + _D("vconf changed: %s", name); + + // Check the time changed event + if (!strcmp(name, VCONFKEY_SYSTEM_TIME_CHANGED)) + { + struct watch_priv *watch_data = data; + + _D("ambient_mode: %d", watch_data->ambient_mode); + + if (watch_data->ambient_mode) + { + __watch_core_ambient_tick(0, NULL); + } + + return; + } + + for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) { + struct evt_ops *eo = &evtops[i]; + + switch (eo->type) { + case _CB_VCONF: + if (!strcmp(name, eo->key.vkey)) + __vconf_do(eo, key, data); + break; + default: + break; + } + } +} + +static int __add_vconf(struct watch_core *wc) +{ + int i; + int r; + + for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) { + struct evt_ops *eo = &evtops[i]; + + switch (eo->type) { + case _CB_VCONF: + r = vconf_notify_key_changed(eo->key.vkey, __vconf_cb, wc); + if (r < 0) + _E("vconf_notify_key_changed error: %d", r); + break; + default: + break; + } + } + + // Add a vconf key for time changed + r = vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, __vconf_cb, &priv); + if (r < 0) + _E("vconf_notify_key_changed error: %d", r); + + return 0; +} + +static int __del_vconf(void) +{ + int i; + int r; + + for (i = 0; i < sizeof(evtops) / sizeof(evtops[0]); i++) { + struct evt_ops *eo = &evtops[i]; + + switch (eo->type) { + case _CB_VCONF: + r = vconf_ignore_key_changed(eo->key.vkey, __vconf_cb); + break; + default: + break; + } + } + + return 0; +} + +static int __aul_handler(aul_type type, bundle *b, void *data) +{ + int ret; + + switch (type) { + case AUL_START: + ret = __watch_appcontrol(data, b); + break; + case AUL_RESUME: + break; + case AUL_TERMINATE: + ret = __watch_terminate(data); + break; + default: + break; + } + + return 0; +} + +EXPORT_API int watch_core_set_event_callback(enum watch_core_event event, + int (*cb) (void *, void *), void *data) +{ + struct watch_core *wc = &core; + struct sys_op *op; + enum sys_event se; + + for (se = SE_UNKNOWN; se < SE_MAX; se++) { + if (event == to_ae[se]) + break; + } + + if (se == SE_UNKNOWN || se >= SE_MAX) { + _E("Unregistered event"); + errno = EINVAL; + return -1; + } + + op = &wc->sops[se]; + + op->func = cb; + op->data = data; + + return 0; +} + +static char* __get_timezone(void) +{ + char buf[TIMEZONE_BUFFER_MAX] = {0,}; + + ssize_t len = readlink(LOCAL_TIME_PATH, buf, sizeof(buf)-1); + + if (len != -1) + { + buf[len] = '\0'; + } + else // handle error condition + { + return vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_ID); + } + + return strdup(buf+20); +} + +static void __get_timeinfo(struct watch_time_s *timeinfo) +{ + UErrorCode status = U_ZERO_ERROR; + + // UTC time + struct timeval current; + gettimeofday(¤t, NULL); + timeinfo->timestamp = current.tv_sec; + + // Time zone + char* timezone = __get_timezone(); + UChar utf16_timezone[64] = {0}; + u_uastrncpy(utf16_timezone, timezone, 64); + + // Local time + UCalendar *cal = ucal_open(utf16_timezone, u_strlen(utf16_timezone), uloc_getDefault(), UCAL_TRADITIONAL, &status); + if (cal == NULL) + return; + + timeinfo->year = ucal_get(cal, UCAL_YEAR, &status); + timeinfo->month = ucal_get(cal, UCAL_MONTH, &status) + 1; + timeinfo->day = ucal_get(cal, UCAL_DATE, &status); + timeinfo->day_of_week = ucal_get(cal, UCAL_DAY_OF_WEEK, &status); + timeinfo->hour = ucal_get(cal, UCAL_HOUR_OF_DAY, &status); + timeinfo->hour24 = ucal_get(cal, UCAL_HOUR_OF_DAY, &status); + timeinfo->minute = ucal_get(cal, UCAL_MINUTE, &status); + timeinfo->second = ucal_get(cal, UCAL_SECOND, &status); + timeinfo->millisecond = ucal_get(cal, UCAL_MILLISECOND, &status); + timeinfo->timezone = timezone; + + timeinfo->hour -= (timeinfo->hour > 12) ? 12 : 0; + timeinfo->hour = (timeinfo->hour == 0) ? 12 : timeinfo->hour; + + ucal_clear(cal); + ucal_close(cal); +} + +int watch_core_init(const char *name, const struct watch_ops *ops, + int argc, char **argv) +{ + int r; + + if (core.init != 0) { + errno = EALREADY; + return -1; + } + + if (ops == NULL || ops->cb_app == NULL) { + errno = EINVAL; + return -1; + } + + r = _set_i18n(name); + _retv_if(r == -1, -1); + + r = __add_vconf(&core); + if (r == -1) { + _E("Add vconf callback failed"); + goto err; + } + + r = aul_launch_init(__aul_handler, &core); + if (r < 0) { + _E("Fail to call the aul_launch_init"); + assert(0); + goto err; + } + + r = aul_launch_argv_handler(argc, argv); + if (r < 0) { + _E("Fail to call the aul_launch_argv_handler"); + goto err; + } + + core.ops = ops; + core.init = 1; + + return 0; + + err: + return -1; +} + +static void __watch_core_alarm_init(void) +{ + int r = 0; + int pid = getpid(); + char appid[APPID_BUFFER_MAX] = {0,}; + r = aul_app_get_appid_bypid(pid, appid, APPID_BUFFER_MAX); + if (r < 0) { + _E("fail to get the appid from the pid : %d", pid); + assert(0); + } + + r = alarmmgr_init(appid); + if (r < 0) { + _E("fail to alarmmgr_init : error_code : %d",r); + assert(0); + } + +} + +static void __watch_core_time_tick_cancel(void) +{ + if (watch_tick) + { + ecore_timer_del(watch_tick); + watch_tick = NULL; + } +} + +static Eina_Bool __watch_core_time_tick(void *data) +{ + _D("state: %d", priv.state); + + if (priv.ops && priv.ops->time_tick && priv.state != WS_PAUSED) + { + struct watch_time_s timeinfo; + __get_timeinfo(&timeinfo); + + // Set a next timer + double sec = (ONE_SECOND - timeinfo.millisecond) / 1000.0; + watch_tick = ecore_timer_add(sec, __watch_core_time_tick, NULL); + + _D("next time tick: %f", sec); + + priv.ops->time_tick(&timeinfo, priv.ops->data); + } + + return ECORE_CALLBACK_CANCEL; +} + +static int __watch_core_ambient_tick(alarm_id_t id, void *data) +{ + _D("state: %d", priv.state); + + if (priv.ops && priv.ops->ambient_tick && priv.state != WS_RUNNING) + { + struct watch_time_s timeinfo; + __get_timeinfo(&timeinfo); + + priv.ops->ambient_tick(&timeinfo, priv.ops->data); + } + + return 0; +} + +static int __widget_create(const char *id, const char *content, int w, int h, void *data) +{ + _D("widget_create"); + + int ret = widget_provider_app_set_data(WATCH_ID, strdup(id)); + if (ret < 0) + _E("Failed to set the watch id: %d", ret); + + if (priv.ops && priv.ops->create) + { + int r = priv.ops->create(w, h, priv.ops->data); + if (r < 0) + { + _E("Failed to initialize the application"); + __exit_loop(NULL); + } + } + + priv.state = WS_CREATED; + + _D("widget_create done"); + + // Alarm init + __watch_core_alarm_init(); + + return WIDGET_ERROR_NONE; +} + +static int __widget_resize(const char *id, int w, int h, void *data) +{ + + return WIDGET_ERROR_NONE; +} + +static int __widget_destroy(const char *id, widget_destroy_type_e reason, void *data) +{ + _D("widget_destory"); + + __exit_loop(NULL); + + return WIDGET_ERROR_NONE; +} + +static int __widget_pause(const char *id, void *data) +{ + _D("widget_pause"); + + __do_app(WE_PAUSE, &priv, NULL); + + return WIDGET_ERROR_NONE; +} + +static int __widget_resume(const char *id, void *data) +{ + _D("widget_resume"); + + __do_app(WE_RESUME, &priv, NULL); + + return WIDGET_ERROR_NONE; +} + +static int __signal_alpm_handler(int ambient, void *data) +{ + _D("_signal_alpm_handler: ambient: %d, state: %d", ambient, priv.state); + + if (priv.ambient_mode == ambient) + { + _E("invalid state"); + return 0; + } + + // Enter the ambient mode + if (ambient) + { + if (priv.state != WS_PAUSED) + { + __do_app(WE_PAUSE, &priv, NULL); + priv.ambient_mode_skip_resume = 0; + } + else + { + priv.ambient_mode_skip_resume = 1; + } + + priv.ambient_mode = 1; + __do_app(WE_AMBIENT, &priv, NULL); + + if (priv.ops && priv.ops->ambient_tick) { + struct watch_time_s timeinfo; + __get_timeinfo(&timeinfo); + + int sec = ONE_MINUTE - timeinfo.second; + + _D("next time tick: %d", sec); + + // Set a next alarm + int r = alarmmgr_add_alarm_withcb(ALARM_TYPE_VOLATILE, sec, 60, + __watch_core_ambient_tick, data, &alarm_id); + if (r < 0) { + _E("fail to alarmmgr_add_alarm_withcb : error_code : %d",r); + } + + priv.ops->ambient_tick(&timeinfo, priv.ops->data); + } + + // Send a update done signal + _watch_core_send_alpm_update_done(); + + } + // Exit the ambient mode + else + { + priv.ambient_mode = 0; + __do_app(WE_AMBIENT, &priv, NULL); + + _D("Resume check: %d", priv.ambient_mode_skip_resume); + if (!priv.ambient_mode_skip_resume) + { + _D("Call the resume after ambient mode changed"); + __do_app(WE_RESUME, &priv, NULL); + } + + // Disable alarm + if (alarm_id) + { + alarmmgr_remove_alarm(alarm_id); + alarm_id = 0; + } + } + + return 0; +} + +static int __watch_core_widget_init(void) +{ + _D("Initialize the widget"); + int r = 0; + + r = widget_provider_app_init_sync(&widget_ops); + if (r != WIDGET_ERROR_NONE) + { + _E("failed to initialize the widget"); + return r; + } + else + { + _D("succeded to initialize the widget"); + } + + return 0; + +} + +static void __watch_core_signal_init(void) +{ + _watch_core_listen_alpm_handler(__signal_alpm_handler, NULL); +} + +static int __before_loop(struct watch_priv *watch, int argc, char **argv) +{ + int r = 0; + + if (argc <= 0 || argv == NULL) { + errno = EINVAL; + _E("argument are invalid"); + return -1; + } + + priv.ambient_mode = 0; + priv.ambient_mode_skip_resume = 0; + +#if !(GLIB_CHECK_VERSION(2, 36, 0)) + g_type_init(); +#endif + + elm_init(argc, argv); + + r = watch_core_init(watch->name, &w_ops, argc, argv); + _retv_if(r < 0, -1); + + r = __watch_core_widget_init(); + _retv_if(r < 0, r); + + __watch_core_signal_init(); + + return 0; +} + +static void __after_loop(struct watch_priv *watch) +{ + if (priv.state == WS_RUNNING && watch->ops && watch->ops->pause) + watch->ops->pause(watch->ops->data); + + priv.state = WS_DYING; + + // Cancel the time_tick callback + __watch_core_time_tick_cancel(); + + if (watch->ops && watch->ops->terminate) + watch->ops->terminate(watch->ops->data); + + widget_provider_app_fini(); + + elm_shutdown(); + + alarmmgr_fini(); +} + + +EXPORT_API int watch_core_main(const char *appid, int argc, char **argv, + struct watchcore_ops *ops) +{ + int r; + + r = __set_data(&priv, appid, ops); + _retv_if(r == -1, -1); + + r = __before_loop(&priv, argc, argv); + if (r != 0) { + return r; + } + + ecore_main_loop_begin(); + + aul_status_update(STATUS_DYING); + + __after_loop(&priv); + + + return 0; +} + +EXPORT_API int watch_core_terminate() +{ + ecore_main_loop_thread_safe_call_sync((Ecore_Data_Cb)__exit_loop, NULL); + return 0; +} + + +EXPORT_API void watch_core_get_timeinfo(struct watch_time_s *timeinfo) +{ + __get_timeinfo(timeinfo); +} + diff --git a/src/watch_app_error.c b/src/watch_app_error.c new file mode 100755 index 0000000..1da14fe --- /dev/null +++ b/src/watch_app_error.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +#include +#include + +#include +#include + +#include "watch_app_private.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION" + +static const char* watch_app_error_to_string(app_error_e error) +{ + switch (error) + { + case APP_ERROR_NONE: + return "NONE"; + + case APP_ERROR_INVALID_PARAMETER: + return "INVALID_PARAMETER"; + + case APP_ERROR_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + + case APP_ERROR_INVALID_CONTEXT: + return "INVALID_CONTEXT"; + + case APP_ERROR_NO_SUCH_FILE: + return "NO_SUCH_FILE"; + + case APP_ERROR_ALREADY_RUNNING: + return "ALREADY_RUNNING"; + + default : + return "UNKNOWN"; + } +} + +int watch_app_error(app_error_e error, const char* function, const char *description) +{ + if (description) + { + LOGE("[%s] %s(0x%08x) : %s", function, watch_app_error_to_string(error), error, description); + } + else + { + LOGE("[%s] %s(0x%08x)", function, watch_app_error_to_string(error), error); + } + + return error; +} diff --git a/src/watch_app_main.c b/src/watch_app_main.c new file mode 100755 index 0000000..d321885 --- /dev/null +++ b/src/watch_app_main.c @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "appcore-watch.h" +#include "appcore-watch-log.h" +#include "watch_app_private.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_WATCH_APPLICATION" + +#define WATCH_ID "internal://WATCH_ID" + +typedef enum { + WATCH_APP_STATE_NOT_RUNNING, // The application has been launched or was running but was terminated + WATCH_APP_STATE_CREATING, // The application is initializing the resources on watch_app_create_cb callback + WATCH_APP_STATE_RUNNING, // The application is running in the foreground and background +} watch_app_state_e; + +typedef struct { + char *package; + char *watch_app_name; + watch_app_state_e state; + watch_app_lifecycle_callback_s *callback; + void *data; +} watch_app_context_s; + +typedef watch_app_context_s *watch_app_context_h; + +struct _watch_time_s +{ + int year; + int month; + int day_of_week; + int day; + int hour; + int hour24; + int minute; + int second; + int millisecond; + time_t timestamp; + char *timezone; +}; + + +#define WATCH_APP_EVENT_MAX 5 +static Eina_List *handler_list[WATCH_APP_EVENT_MAX] = {NULL, }; +static int _initialized = 0; + +struct app_event_handler { + app_event_type_e type; + app_event_cb cb; + void *data; +}; + +struct app_event_info { + app_event_type_e type; + void *value; +}; + +struct watch_app_context { + char *appid; + watch_app_state_e state; + watch_app_lifecycle_callback_s *callback; + void *data; +}; + +static void _free_handler_list(void) +{ + int i; + app_event_handler_h handler; + + for (i = 0; i < WATCH_APP_EVENT_MAX; i++) { + EINA_LIST_FREE(handler_list[i], handler) + free(handler); + } + + eina_shutdown(); +} + +static int _watch_core_low_memory(void *event_info, void *data) +{ + Eina_List *l; + app_event_handler_h handler; + struct app_event_info event; + + _I("watch_app_low_memory"); + + event.type = APP_EVENT_LOW_MEMORY; + event.value = event_info; + + EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_MEMORY], l, handler) { + handler->cb(&event, handler->data); + } + + return APP_ERROR_NONE; +} + +static int _watch_core_low_battery(void *event_info, void *data) +{ + Eina_List *l; + app_event_handler_h handler; + struct app_event_info event; + + _I("watch_app_low_battery"); + + event.type = APP_EVENT_LOW_BATTERY; + event.value = event_info; + + EINA_LIST_FOREACH(handler_list[APP_EVENT_LOW_BATTERY], l, handler) { + handler->cb(&event, handler->data); + } + + return APP_ERROR_NONE; +} + +static int _watch_core_lang_changed(void *event_info, void *data) +{ + Eina_List *l; + app_event_handler_h handler; + struct app_event_info event; + + _I("_watch_core_lang_changed"); + + event.type = APP_EVENT_LANGUAGE_CHANGED; + event.value = event_info; + + EINA_LIST_FOREACH(handler_list[APP_EVENT_LANGUAGE_CHANGED], l, handler) { + handler->cb(&event, handler->data); + } + + return APP_ERROR_NONE; +} + +static int _watch_core_region_changed(void *event_info, void *data) +{ + Eina_List *l; + app_event_handler_h handler; + struct app_event_info event; + + _I("_ui_app_appcore_region_changed"); + + event.type = APP_EVENT_REGION_FORMAT_CHANGED; + event.value = event_info; + + EINA_LIST_FOREACH(handler_list[APP_EVENT_REGION_FORMAT_CHANGED], l, handler) { + handler->cb(&event, handler->data); + } + + return APP_ERROR_NONE; +} + + +static void _watch_core_set_appcore_event_cb(struct watch_app_context *app_context) +{ + watch_core_set_event_callback(WATCH_CORE_EVENT_LOW_MEMORY, _watch_core_low_memory, app_context); + watch_core_set_event_callback(WATCH_CORE_EVENT_LOW_BATTERY, _watch_core_low_battery, app_context); + watch_core_set_event_callback(WATCH_CORE_EVENT_LANG_CHANGE, _watch_core_lang_changed, app_context); + watch_core_set_event_callback(WATCH_CORE_EVENT_REGION_CHANGE, _watch_core_region_changed, app_context); +} + +static void _watch_core_unset_appcore_event_cb(void) +{ + watch_core_set_event_callback(WATCH_CORE_EVENT_LOW_MEMORY, NULL, NULL); + watch_core_set_event_callback(WATCH_CORE_EVENT_LOW_BATTERY, NULL, NULL); + watch_core_set_event_callback(WATCH_CORE_EVENT_LANG_CHANGE, NULL, NULL); + watch_core_set_event_callback(WATCH_CORE_EVENT_REGION_CHANGE, NULL, NULL); +} + + +static int _watch_core_create(int w, int h, void *data) +{ + _W("_watch_core_create"); + struct watch_app_context *app_context = data; + watch_app_create_cb create_cb; + + if (app_context == NULL) { + return watch_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + _watch_core_set_appcore_event_cb(app_context); + + create_cb = app_context->callback->create; + + if (create_cb == NULL || create_cb(w, h, app_context->data) == false) { + return watch_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "watch_app_create_cb() returns false"); + } + + app_context->state = WATCH_APP_STATE_RUNNING; + + return APP_ERROR_NONE; +} + +static int _watch_core_control(app_control_h app_control, void *data) +{ + _W("_watch_core_control"); + struct watch_app_context *app_context = data; + watch_app_control_cb app_control_cb; + + if (app_context == NULL) + return watch_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + + app_control_cb = app_context->callback->app_control; + + if (app_control_cb != NULL) + app_control_cb(app_control, app_context->data); + + return APP_ERROR_NONE; +} + +static int _watch_core_pause(void *data) +{ + _W("_watch_core_pause"); + struct watch_app_context *app_context = data; + watch_app_pause_cb pause_cb; + + if (app_context == NULL) + return watch_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + + pause_cb = app_context->callback->pause; + + if (pause_cb != NULL) + pause_cb(app_context->data); + + return APP_ERROR_NONE; +} + +static int _watch_core_resume(void *data) +{ + _W("_watch_core_resume"); + struct watch_app_context *app_context = data; + watch_app_resume_cb resume_cb; + + if (app_context == NULL) + return watch_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + + resume_cb = app_context->callback->resume; + + if (resume_cb != NULL) + resume_cb(app_context->data); + + return APP_ERROR_NONE; +} + +static int _watch_core_terminate(void *data) +{ + _W("_watch_core_terminate"); + struct watch_app_context *app_context = data; + watch_app_terminate_cb terminate_cb; + + if (app_context == NULL) + return watch_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + + terminate_cb = app_context->callback->terminate; + + if (terminate_cb != NULL) + terminate_cb(app_context->data); + + _watch_core_unset_appcore_event_cb(); + + if (_initialized) + _free_handler_list(); + + return APP_ERROR_NONE; +} + +static void _watch_core_time_tick(void *watchtime, void *data) +{ + _I("_watch_core_time_tick"); + struct watch_app_context *app_context = data; + watch_app_time_tick_cb time_tick_cb; + + if (app_context == NULL) + return; + + time_tick_cb = app_context->callback->time_tick; + + if (time_tick_cb != NULL) + time_tick_cb((watch_time_h)watchtime, app_context->data); +} + +static void _watch_core_ambient_tick(void *watchtime, void *data) +{ + _W("_watch_core_ambient_tick"); + struct watch_app_context *app_context = data; + watch_app_ambient_tick_cb ambient_tick_cb; + + if (app_context == NULL) + return; + + ambient_tick_cb = app_context->callback->ambient_tick; + + if (ambient_tick_cb != NULL) + ambient_tick_cb((watch_time_h)watchtime, app_context->data); +} + +static void _watch_core_ambient_changed(int ambient, void *data) +{ + _W("_watch_core_ambient_changed: %d", ambient); + struct watch_app_context *app_context = data; + watch_app_ambient_changed_cb ambient_changed_cb; + + if (app_context == NULL) + return; + + ambient_changed_cb = app_context->callback->ambient_changed; + + if (ambient_changed_cb != NULL) + ambient_changed_cb((bool)ambient, app_context->data); +} + + +EXPORT_API int watch_app_main(int argc, char **argv, watch_app_lifecycle_callback_s *callback, void *user_data) +{ + struct watch_app_context app_context = { + .appid = NULL, + .state = WATCH_APP_STATE_NOT_RUNNING, + .callback = callback, + .data = user_data + }; + + struct watchcore_ops watchcore_context = { + .data = &app_context, + .create = _watch_core_create, + .app_control = _watch_core_control, + .pause = _watch_core_pause, + .resume = _watch_core_resume, + .terminate = _watch_core_terminate, + .time_tick = _watch_core_time_tick, + .ambient_tick = _watch_core_ambient_tick, + .ambient_changed = _watch_core_ambient_changed, + }; + + if (argc <= 0 || argv == NULL || callback == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + if (callback->create == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "watch_app_create_cb() callback must be registered"); + + if (app_context.state != WATCH_APP_STATE_NOT_RUNNING) + return watch_app_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL); + + if (app_get_id(&(app_context.appid)) != APP_ERROR_NONE) + return watch_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the appid"); + + app_context.state = WATCH_APP_STATE_CREATING; + + watch_core_main(app_context.appid, argc, argv, &watchcore_context); + + free(app_context.appid); + + return APP_ERROR_NONE; +} + +EXPORT_API void watch_app_exit(void) +{ + _I("watch_app_exit"); + watch_core_terminate(); +} + +EXPORT_API int watch_app_add_event_handler(app_event_handler_h *event_handler, app_event_type_e event_type, app_event_cb callback, void *user_data) +{ + app_event_handler_h handler; + Eina_List *l_itr; + + if (!_initialized) { + eina_init(); + _initialized = 1; + } + + if (event_handler == NULL || callback == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + if (event_type < APP_EVENT_LOW_MEMORY || event_type > APP_EVENT_REGION_FORMAT_CHANGED) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + EINA_LIST_FOREACH(handler_list[event_type], l_itr, handler) { + if (handler->cb == callback) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + handler = calloc(1, sizeof(struct app_event_handler)); + if (!handler) + return watch_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + + handler->type = event_type; + handler->cb = callback; + handler->data = user_data; + handler_list[event_type] = eina_list_append(handler_list[event_type], handler); + + *event_handler = handler; + + return APP_ERROR_NONE; +} + +EXPORT_API int watch_app_remove_event_handler(app_event_handler_h event_handler) +{ + app_event_handler_h handler; + app_event_type_e type; + Eina_List *l_itr; + Eina_List *l_next; + + if (event_handler == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + if (!_initialized) { + _I("handler list is not initialized"); + return APP_ERROR_NONE; + } + + type = event_handler->type; + if (type < APP_EVENT_LOW_MEMORY || type > APP_EVENT_REGION_FORMAT_CHANGED) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + EINA_LIST_FOREACH_SAFE(handler_list[type], l_itr, l_next, handler) { + if (handler == event_handler) { + free(handler); + handler_list[type] = eina_list_remove_list(handler_list[type], l_itr); + return APP_ERROR_NONE; + } + } + + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "cannot find such handler"); +} + +EXPORT_API int watch_time_get_current_time(watch_time_h* watch_time) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + struct watch_time_s *time_info; + + time_info = calloc(1, sizeof(struct watch_time_s)); + if (time_info == NULL) + return watch_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a handle"); + + watch_core_get_timeinfo(time_info); + + *watch_time = (struct _watch_time_s *)time_info; + + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_delete(watch_time_h watch_time) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + if (watch_time->timezone) + free(watch_time->timezone); + + free(watch_time); + + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_year(watch_time_h watch_time, int *year) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *year = watch_time->year; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_month(watch_time_h watch_time, int *month) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *month = watch_time->month; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_day(watch_time_h watch_time, int *day) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *day = watch_time->day; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_day_of_week(watch_time_h watch_time, int *day_of_week) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *day_of_week = watch_time->day_of_week; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_hour(watch_time_h watch_time, int *hour) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *hour = watch_time->hour; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_hour24(watch_time_h watch_time, int *hour24) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *hour24 = watch_time->hour24; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_minute(watch_time_h watch_time, int *minute) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *minute = watch_time->minute; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_second(watch_time_h watch_time, int *second) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *second = watch_time->second; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_millisecond(watch_time_h watch_time, int *millisecond) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *millisecond = watch_time->millisecond; + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_utc_time(watch_time_h watch_time, struct tm *utc_time) +{ + if (watch_time == NULL || utc_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + time_t timestamp = watch_time->timestamp; + + gmtime_r(×tamp, utc_time); + + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_utc_timestamp(watch_time_h watch_time, time_t *utc_timestamp) +{ + if (watch_time == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *utc_timestamp = watch_time->timestamp; + + return APP_ERROR_NONE; +} + +EXPORT_API int watch_time_get_time_zone(watch_time_h watch_time, char **time_zone_id) +{ + if (watch_time == NULL || watch_time->timezone == NULL || time_zone_id == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + *time_zone_id = strdup(watch_time->timezone); + + return APP_ERROR_NONE; +} + +EXPORT_API int watch_app_get_elm_win(Evas_Object **win) +{ + Evas_Object *ret_win = NULL; + char *id = widget_provider_app_get_data(WATCH_ID); + + if (win == NULL) + return watch_app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + + if (id) { + Evas *e; + e = widget_get_evas(id); + + if (e) { + Evas_Object *widget_parent; + widget_parent = evas_object_rectangle_add(e); + + if (widget_parent) { + ret_win = elm_win_add(widget_parent, id, ELM_WIN_TIZEN_WIDGET); + evas_object_del(widget_parent); + if (!ret_win) { + LOGE("win is NULL\n"); + return watch_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + } else { + LOGE("Failed to get parent widget"); + return watch_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + } else { + LOGE("parent evas object is NULL\n"); + return watch_app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + } else { + LOGE("id is NULL\n"); + return watch_app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + *win = ret_win; + return APP_ERROR_NONE; +} + diff --git a/src/watch_app_private.h b/src/watch_app_private.h new file mode 100755 index 0000000..65a6c04 --- /dev/null +++ b/src/watch_app_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +#ifndef __WATCH_APP_PRIVATE_H__ +#define __WATCH_APP_PRIVATE_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int watch_app_error(app_error_e error, const char* function, const char *description); + +#ifdef __cplusplus +} +#endif + +#endif /* __WATCH_APP_PRIVATE_H__ */ -- 2.7.4