From 8fe9c25e35e50d9c26c78ee78c0210c4c12705a2 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Wed, 29 Nov 2017 10:53:37 -0800 Subject: [PATCH 01/13] Update asset for no search result image Bug: 68863351 Test: visual Change-Id: Ia4d411e5d7d1db8b321fdfde006a93c6ff52ecb3 (cherry picked from commit cb721bd870f73af7e156076f5fe57314436a5312) --- res/drawable-hdpi/empty_search_results.png | Bin 51332 -> 0 bytes res/drawable-mdpi/empty_search_results.png | Bin 40046 -> 0 bytes res/drawable-xhdpi/empty_search_results.png | Bin 60334 -> 0 bytes res/drawable-xxhdpi/empty_search_results.png | Bin 76829 -> 0 bytes res/drawable-xxxhdpi/empty_search_results.png | Bin 70660 -> 0 bytes res/drawable/empty_search_results.xml | 30 ++++++++++++++++++ res/layout/search_panel.xml | 4 +-- 7 files changed, 32 insertions(+), 2 deletions(-) delete mode 100644 res/drawable-hdpi/empty_search_results.png delete mode 100644 res/drawable-mdpi/empty_search_results.png delete mode 100644 res/drawable-xhdpi/empty_search_results.png delete mode 100644 res/drawable-xxhdpi/empty_search_results.png delete mode 100644 res/drawable-xxxhdpi/empty_search_results.png create mode 100644 res/drawable/empty_search_results.xml diff --git a/res/drawable-hdpi/empty_search_results.png b/res/drawable-hdpi/empty_search_results.png deleted file mode 100644 index 6202a330221cfe89ea98600e52183ac9d78f3290..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51332 zcmeFZ1yq&W)<3)n0g(m)3F(v#Y`Q_Z8|m0=Hr zAbbzT(Q}UH-pl_TcZ_#@uX_xHy`DMeTI)As%{ABZ30GB?!9*uP2Z2DCa<7U!U(_80LRYbpkWf{%bZ~WWv2<{xl#`I4baZww zx3YzUK%NsB8Wx%wtAxV)(|h6yVgB(74(gZDDAmR9_!Gp?GgDo}kq@KF8NaO7gexV5 zOxlqhh7=X$A9-1g1tS7|40Vy}epFCySVY&++^t-jk-Gim-jk|Pk(H9&jLLr0Ml_5> zSxz->e~cpWtGKg4?X7Kdi>zV+=(LU?9JER^DwoeR2%rOBA)#y3ji~h?1kd41XrM-= zv_^Ka&{OPp;wc6Q{=o>1t}%QHX#NBsv71ri1t2kL1pka=dJRxEGRUMGX1V}U1%pf& z{FaA7{uu`;w-7-3@l=-)vSUD$`0y}Ekfk7~r2j^Q6iA01L}0Ga$`2X?gV^P?&1FH4 zpMo0ua4uDV&@e#kYGJpTK*+a1CLJ_1o}l0q5P|fLw$S#qGMp7=0I8G;p&D9#sQ`U6 zuoJ4bHtSW!J~^Um1UyhgXsQ@%vscO$jsPy~+1(xxC_CmdFx%bFo_$zleSJJp)mX;h zcMT|~)TX8jCrkasj$$CtoU8BP2@6{#iN7F0AcK4`+uXCK zm`~OpdokGb&2qHN@zYDE$K=D*t#YO{I?MzMYIsgjlBtoq9QoAY;;~FG>4r|t=4V)r zkVIyPi; zgbqy<8d1va1F9xjWV}1Hl$~J&YSaob+_Dh$2u(^YS@IoWXGH!`1L@~6f*l}^z~hiQ z8AyCUg_`gyj4Fwm2fQS~()TY7n7KkyqY1Oq2ArRe2uJedtPB)eVoyYiNVKyzz9mNG zY_(-)ZEF!P=VQ4T2kS1UF2N{nBYAwI1gSRs1FXN?0~s$ss_`NZvWGY&^y+n49Yr1G zG1&){WVBqk6Bl_eA_c28Gf>ApPV#8kZ~yO@B2wT|118H+88oQtH3R6F|U z8Kz=Rc?TNvjOtz1@>iB{mbjKs;K>}sf1CcQ=4^T5Cixg69UX2EzRjTn{K z;))0Hqh!T`E5moLv}>~SLe`R3Qm|7Tv~-xOnY}N^bfG86C(tL5GP7wGJuG-Q{qU03 zu2#2ZbdiyUPnon9r^Z6j#aD^NS`RZ+*EC2qEQ$mlgg&%*;Gij*=d1fU97VT9u|-89 zPc6ILc%iP1@)GPyr6&uO4Q6qOTL5<}eR=P=w>xuf@@MkeJHii(a`+`U&IGZ|m{v=Idzb8CFV{W|Y#6 z)Rxv3;uh8@$0-+Qj##uj-mdPfE_!<9@zNN|WLdRcwGY(7l*r=g%d(b@xEFCg&wcKG z7DmMk9mgsr*CY3JdE!hUa6@1^wJ&``)aT`1;wqbkPCrin80SJYem7IARfa~|u#5$f zMU6|)ZrGi0g}`psBoWp$(zdCN7mM<)ADj&5ZVr9ONUKb1UVkw8XoF|NY9sVbRu5Me zQ>HGb%Rozq#H`xVpy;Kn1a_O55?>Vwl>m#X6&f}eTa0$;=;NpP9uN1Sn?xcXMVzx1 zL>7d2r#Yr|jeB?-pLRU$R%vm_G`>9};YV|7c6#%45LD<-hhTve9&kNCAMxnmrZ-hX zl&HWY{A0!V`t``{n(LRZM+cS$E;W@>S$4d?S4y?NlH3>5XN7fJ)%Wel04j7DdZ)z~ zgW-1QZS4@zD911zl0irkx5wZc36~kkPm+m}(`gnE75+zHd2VKrhpg5@6THv4o{P4z zn(Oww*2&P3vsEDDXJszqvA3K-qtkZS8 zX1uxB>iiG|Z7{jc@{1B{{t6){uSxWU%NMSN+(0Q2dKOX5Z1-BFcwIZG%=ZQTO(mNE zqo%IFrYZ!RwM$y)OSgU2-i)prs_3xk&Qw7^g=CP5Tn>*YBbX#gy6iW`_{MXIG}NK1 zA>~c{lcM6*8nb@$A@kMcX>g`KR^r2?Y7%<+jQm@_w?tbh0@HOZFL%Q#sZR4q}H z+aUC;4qn*V*DENhnWwp@`AL&!V`!=hI(lF~xIucW?jzUx*OU5n`=3QR>nF7kw3J?( zzlI;l9aZj&mW4lDJxDyVGb~lMb6Rgl8bbPvN`qBBTJ!2P`H--tdi2P(H5sgSiu#j` zO%E_852n`L^tO2#M@g^6)%}Yz`&TgqCfp-$mCT_IQ@E2`kh58fr|zUmr)i`f>6_|5 zSLqQM9CRT(Yz8Pz5 zht20Wu5&|Dr*~Ea>je7@cAmNJR7@`6Yd_OYeI#IP_s;d5&`I2|N_%a3ZE9JKflbZE z%@rEbSJjge5XRuWky(#?|Pc0A2KWGdT9>raWi#tU|O5Qz&ae^m7Ak`Er zO&wPqB}D<4gB>f>%)u1S>S^Z)B%&aYkf^646lMc=r8I?GSlJ6xZ`L+YQ(Bn`Q)_c8 zu`4-Bz%8w0Z#u&@ZYpcSZrZ^3&8S61(1kn&00DMzS16^Yovpo#fTu9^7r6q!-)GHi z)RbRHTy2D@ub*{DsiUMyDdFG@r{rek2E*7nAe6lPtPpN)US19sN)C1i7aKc-4Z;bA z@C$Hp39z$Me)~|1paXviIh&aas7p$J>kjxPOl|4v>L|d*=HcPN>cPqC;B3JL;pgXP zW9MMw-~a;@U>7fYSEwi0-i79?kneIN;Vv*|D@Ru=2YbphxlmIFH&a&ji_Sb#rlbhPpa9|C;?Lf`3H74E6`Fqnoqs7v-42*x3yE)H(aFgQT|OWa&srQ88y_-0)H zfgmY&U`oFf<@l48{z(w<0Dyq=mlJXPz61RA82)(tkJ!6fng0V2XHWi-4en|64{T>o zzOsFB#jhSB1gJ_t!Wn*MCz=ipwjy7>{Kx(k*uI{5H6^1G6lP_Awy9+jV*4x854-&# z4=xFHg^K{ZykK@7Fgu4Pgj0ZBM^Qg0{w_xe>UlN;4Xc~*FR>CB zmJ9qW{s>cl_oP39>o?2z62SyKM0mK^S=qmQgxJ2f{pbK77W&$1`3p+RpG@rsrJKE# ztB9%tFc+8aBEK~KkopHuKaKk*QD;_mrUX@6z{ZrJc7SGn@SgQ^wj5}{o&MbV{ei8O zh=do^UWo0C3i$FT)}M%!0KkBi=ik!l!fkCGJpL`2xGk_i|C;J+>z@bw2L!*IA1ap7KloUk3a$(O+@> zvz#;I6ZskjzA=4i`9~%R2U`cgp{D~y_wZnp+>?M>f#~-9EduY3jo{aF9`nq`A;+a%KsfVIZ2VP^(iw4n3b8pAG>G) zQ*(1TA3u~I%*SsE6rUixP_QW{4=|I=;_Aofm z5zsTM70?M6pE<8NACw2o#|JkDb8$d;z@~664zL;2oP(Pa%EQge$MJn0Ke7K!w2HG8 zP?>|;{?xsj8z3Lb1L5Uk=Q0O#@W4&M5GWTrn4gOi4(2e0Lpk`lcp-2o-*@@Hkny*E zB;n3h?r<|{X9v6gFx3S%a6lPF!0N}`zYGil=i`I$nz4gTVH|L<8H5WCHs$9q1NQQ~ za1JhRE*Lwf+1dW>FT6hnbe3^_eGI7Ui`{>N)eM+6j2&vuW6sL~<}x+q1#@u$u=1Jm z^MiTK0p-EC*<)9=!MV*izNhyM|>Uq|>08NccZ*v$WfA%7L~m*+o3eAnPl+WE<8 zzqyI5l?zaZ@%rh(_oVgDd&956?7KIgIq1LN&wu0jQWq0|!p@vg#03f%${EN&t?YZ- zk0F2MI2*xNf}iZ;yKnHD0To~lI6Ih|p9co!GUwz3LruB4!Dc)><}fopGhPTMkO2IR z{h#~rumtuAKNpSI&x%H8HKeZvpRc06Q2nzI7YB1!51{UH{cQjKt)eCOqaI56%bM0# z$$w`3=PqEDK==fk{#Ug3pSs|gb^N6KzfSRoh5Su> zUrK%u$ZzeP>F=8xee*q-gFR5ub3KRu0X`1YUR>eME+Xbv?(>z1s zr_AZAXa6MauU-BZ=lnm8u;x%sC_fNJ!B7aC3(Um}GXoZ3J{~X!FAUBOgYfg3ou%6U z&k^=(Nu6DQ^M4*;|IL}f|H1hBpJk5!L*4y+9P(Av|HJC|ze#srz46Zp&-d)Gf<4BgaD_zKnn6FsvrI@^hanE__84c&XV9Fz((O$ z&A;RVu6F{RpWW^haRCaclyXuMJP>{!z&}|5xBMaIC%T{HoSoze06G2HF~gUH4B+`& z+h6H*&JJvB-M-KR)u*!$8&Ci~o8=eYpP&DgSNGrW{`~x}ygyjA&dzUuJEm6;?D{B*;@YJ`23jCe?$5=nZG+Z7r4LS`VH5)5I7g{Z|nLE z*SQcl7x8cF`VH5)5I7g{Z|nLE*SQcl7x8cF`VH5)5I7g{Z|nLE*SQcl7x8cF`VH5) z5I7g{Z|nLE*SQcl7x8cF`VH5)5I7g{Z|nLE*SQcl7x8cF`VH5)5I7g{Z|nLE*SQcl z7x8cF`VH5)5I7g{Z|nLE*SQcl7x8cF`VH5)5I7g{Z|nLE*SQcl7x8cF`VH5)5I7g{ zZ|nLE*SQcl7x8cF`VH5)5I7g{zqBs&AMYCk{zI%VwFmGvL84rbHsDQ!lrUL!B@pN) z9SGzf1OgqN0>4*5AUAdp=$#1&B#;aO5jn&fzmx`n?9k;TuWNcvyno@5Zm8|G`PtBB z-Fae9B-aQ$?)-AhHIk}HjFJ{v7BK)sghqGKY9Et#u3)8L%F#jA9uIE_jdpJUvyGUP zh~55~T=jFVp*{DBGMg8E?|r0ctWxu=V*7WYoI5=!{6{4(eAm1(XNH3zA+qd`79fM6JH#LeuI^5F}7o|&OIi21MfHZ4mbZQ1e7yF!r=vr1i|ek97c zPLOJmrXv|@x4;o>J&LbGFctIKn&wbgfARYSscG} z4nyV;!?HxW8IZa64ka}JCHtO;Hvht*w7+sgqCYh|0tSd-cnz5yT@%FS<74;^RMve# zC=JVmb0F!Ymi#TEz;H46g&t_1?6e*`vM`(cLdcK}4lzPVfbXp8r_Bc^vS%FQu_{f^ zaK}(=FYtiU)VJJOhFzRBdZ&c5%Hsp~aU6;H(8)j_kz~{xlh&diW6fH`x*`Y$T=QQ6 z37Ui4z#Gx2DJO3@eQzLr)M$Ls2y3j@3>wYHn$5?Bgu3YM-qIGE2v|WFMH)p&%0DS~ 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 qRk&MPmX<mJ$I$LQuM-L{d@^P*hq_5Rm*| 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

IO!O&MJ}}XnG$HChk|@;t}b5oh(# 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 diff --git a/res/drawable-xxhdpi/empty_search_results.png b/res/drawable-xxhdpi/empty_search_results.png deleted file mode 100644 index 4c549bcaec2fcbbf6dfa8bcfe68b11b9f59d2948..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76829 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 diff --git a/res/drawable-xxxhdpi/empty_search_results.png b/res/drawable-xxxhdpi/empty_search_results.png deleted file mode 100644 index 1aed6ad18c35d522483b9c3058fd48e2426013fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70660 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⩔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¨K}?F zgc?XAFCG3}i6nC)eMSk`gk$l`nZ9!u@`yNrXZ+W%8PoUiIZWnG`>5Nd+J?{w$W)V7 ztQs~;{^PPPJRk7Rqt6W$VF6{Mt;_MB*7PpC0CVEg0$z-{^@j!!QT7M|D;D%WF)dh< zM}4RDMAt}ozt}*gqM7pN6qq@$#ZDNX(H6l{3Z`<*Xq^b&FpzkP0K?SvBpE|)a)Am! zmK1<3HM#?776>7NB>0(|>55#qxh(p(=&J7(){vSeZ#y~x*)VBT3IFcx$?wT*y4W7( z&ymGMKr{uIHC0%=%ypQ?9Bpk`xp0A9?-G}0gWckZ#ZsvGPLFVhKsbw~GGn^dzA)|9 zyf~+uAQCO`(&sNUL-o*g{kfFdvieJ<;3BcN%m4;DLwb{a*OrH5!U2gRzm0BB)K2)0 z2k(Gjd4Vz(ReG)prNloV+Q8O`;*K;RHJ^ht$2<*K=~xpN>qxs#GO)3;J-%!005?B+Y%AQ32-$Q9LO{& zx3Q#?$xG_s$lrQ^Y_f1B>J9ui?vYlk9g$s;rb-=KNt3T_N@qAfJ9cIIa1Z5(9Mh4RgJbf)^vq@pI<22>!E@OIW01f%q=VZNjgQ zq!uXO|C+G5hE(LkCqH}t+rLHPGglRoJR{0vXKL~ITHZ3O=#e4n}pePt9$oGLR zRg7{X!>U|#MXweUlU5nJq0gA_i3h#Ujh$SZnwzss#lpp;!BsY-C5ZTNE+b@Mk|91# zCb}#&KkSprv}mf?w$)2{HrZ`%yGfohT&^!*@x8ExWdGyS5>^~HqC8y8i_5w%dYa4K3E zY-kxiw2h4>6Y11bLbB;cc{%$B1sMR+GTUkp3m#opnssaxCm51@m}_miEBl1-q%a?- zVnC!&)#iI@h?8141QG;%~m{s0!X_xQ#(rM}{Ew zfd98f0Rd(w1^xs9r!O1}xCQ14oM5`4p + + + + + + \ No newline at end of file diff --git a/res/layout/search_panel.xml b/res/layout/search_panel.xml index 48a1d4ce1e5..b8e7ae13b2f 100644 --- a/res/layout/search_panel.xml +++ b/res/layout/search_panel.xml @@ -85,8 +85,8 @@ android:layout_height="?android:attr/actionBarSize"/> From b277557991f26190f4594936830b9eb9cf82278a Mon Sep 17 00:00:00 2001 From: Matthew Fritze Date: Tue, 5 Dec 2017 10:46:47 -0800 Subject: [PATCH 02/13] Depend settings on slices in the support library Test: make Bug: 67996923 Change-Id: Ifcb544424df27f3faa8872e6266de286cc706d59 --- Android.mk | 9 +++++++-- proguard.flags | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Android.mk b/Android.mk index c59d938f319..b9121ec19d9 100644 --- a/Android.mk +++ b/Android.mk @@ -20,13 +20,16 @@ LOCAL_USE_AAPT2 := true LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_STATIC_ANDROID_LIBRARIES := \ + android-slices-builders \ + android-slices-core \ + android-slices-view \ android-support-v4 \ android-support-v13 \ android-support-v7-appcompat \ android-support-v7-cardview \ android-support-v7-preference \ android-support-v7-recyclerview \ - android-support-v14-preference + android-support-v14-preference \ LOCAL_JAVA_LIBRARIES := \ bouncycastle \ @@ -34,8 +37,10 @@ LOCAL_JAVA_LIBRARIES := \ ims-common LOCAL_STATIC_JAVA_LIBRARIES := \ + apptoolkit-arch-core-runtime \ + apptoolkit-lifecycle-extensions \ jsr305 \ - settings-logtags + settings-logtags \ LOCAL_PROGUARD_FLAG_FILES := proguard.flags diff --git a/proguard.flags b/proguard.flags index 7a403a4490c..0a299ed2340 100644 --- a/proguard.flags +++ b/proguard.flags @@ -27,6 +27,9 @@ -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet, int); } +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet, int, int); +} # Keep annotated classes or class members. -keep @android.support.annotation.Keep class * From 47f6e548953ccf8ec5889a79f37f561070e59cb9 Mon Sep 17 00:00:00 2001 From: Jaekyun Seok Date: Thu, 30 Nov 2017 18:10:34 +0900 Subject: [PATCH 03/13] Move codes generating html file from xml files to SettingsLib (1/2) LicenseHtmlGeneratorFromXml, LicenseHtmlLoader and indirecly AsyncLoader shoud be commonly used by Settings and TvSettings. So this CL will move them to SettingsLib. Test: building succeeded and tested on sailfish. make ROBOTEST_FILTER=SettingsLicenseActivityTest RunSettingsRoboTests Change-Id: I12e9169b1d3d313a6c5da0d575a6526327268381 --- .../settings/LicenseHtmlGeneratorFromXml.java | 292 ------------------ .../android/settings/LicenseHtmlLoader.java | 110 ------- .../settings/SettingsLicenseActivity.java | 9 +- .../FetchPackageStorageAsyncLoader.java | 2 +- .../suggestions/SuggestionLoader.java | 2 +- .../settings/datausage/AppPrefLoader.java | 2 +- .../storage/StorageAsyncLoader.java | 2 +- .../deviceinfo/storage/UserIconLoader.java | 2 +- .../deviceinfo/storage/VolumeSizesLoader.java | 2 +- .../settings/fuelgauge/BatteryInfoLoader.java | 2 +- .../fuelgauge/BatteryStatsHelperLoader.java | 2 +- .../fuelgauge/DebugEstimatesLoader.java | 2 +- .../settings/fuelgauge/PowerUsageBase.java | 2 +- .../fuelgauge/anomaly/AnomalyLoader.java | 2 +- .../settings/search/SavedQueryLoader.java | 2 +- .../settings/search/SavedQueryRecorder.java | 2 +- .../settings/search/SavedQueryRemover.java | 2 +- .../settings/search/SearchResultLoader.java | 2 +- .../android/settings/utils/AsyncLoader.java | 109 ------- .../LicenseHtmlGeneratorFromXmlTest.java | 125 -------- .../settings/LicenseHtmlLoaderTest.java | 109 ------- .../settings/SettingsLicenseActivityTest.java | 8 +- 22 files changed, 22 insertions(+), 770 deletions(-) delete mode 100644 src/com/android/settings/LicenseHtmlGeneratorFromXml.java delete mode 100644 src/com/android/settings/LicenseHtmlLoader.java delete mode 100644 src/com/android/settings/utils/AsyncLoader.java delete mode 100644 tests/robotests/src/com/android/settings/LicenseHtmlGeneratorFromXmlTest.java delete mode 100644 tests/robotests/src/com/android/settings/LicenseHtmlLoaderTest.java diff --git a/src/com/android/settings/LicenseHtmlGeneratorFromXml.java b/src/com/android/settings/LicenseHtmlGeneratorFromXml.java deleted file mode 100644 index 7025c5adf3f..00000000000 --- a/src/com/android/settings/LicenseHtmlGeneratorFromXml.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings; - -import android.support.annotation.VisibleForTesting; -import android.text.TextUtils; -import android.util.Log; -import android.util.Xml; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.zip.GZIPInputStream; - -/** - * The utility class that generate a license html file from xml files. - * All the HTML snippets and logic are copied from build/make/tools/generate-notice-files.py. - * - * TODO: Remove duplicate codes once backward support ends. - */ -class LicenseHtmlGeneratorFromXml { - private static final String TAG = "LicenseHtmlGeneratorFromXml"; - - private static final String TAG_ROOT = "licenses"; - private static final String TAG_FILE_NAME = "file-name"; - private static final String TAG_FILE_CONTENT = "file-content"; - private static final String ATTR_CONTENT_ID = "contentId"; - - private static final String HTML_HEAD_STRING = - "\n" + - "\n" + - "" + - "\n" + - "

\n" + - "
    "; - - private static final String HTML_MIDDLE_STRING = - "
\n" + - "
\n" + - ""; - - private static final String HTML_REAR_STRING = - "
"; - - private final List mXmlFiles; - - /* - * A map from a file name to a content id (MD5 sum of file content) for its license. - * For example, "/system/priv-app/TeleService/TeleService.apk" maps to - * "9645f39e9db895a4aa6e02cb57294595". Here "9645f39e9db895a4aa6e02cb57294595" is a MD5 sum - * of the content of packages/services/Telephony/MODULE_LICENSE_APACHE2. - */ - private final Map mFileNameToContentIdMap = new HashMap(); - - /* - * A map from a content id (MD5 sum of file content) to a license file content. - * For example, "9645f39e9db895a4aa6e02cb57294595" maps to the content string of - * packages/services/Telephony/MODULE_LICENSE_APACHE2. Here "9645f39e9db895a4aa6e02cb57294595" - * is a MD5 sum of the file content. - */ - private final Map mContentIdToFileContentMap = new HashMap(); - - static class ContentIdAndFileNames { - final String mContentId; - final List mFileNameList = new ArrayList(); - - ContentIdAndFileNames(String contentId) { - mContentId = contentId; - } - } - - private LicenseHtmlGeneratorFromXml(List xmlFiles) { - mXmlFiles = xmlFiles; - } - - public static boolean generateHtml(List xmlFiles, File outputFile) { - LicenseHtmlGeneratorFromXml genertor = new LicenseHtmlGeneratorFromXml(xmlFiles); - return genertor.generateHtml(outputFile); - } - - private boolean generateHtml(File outputFile) { - for (File xmlFile : mXmlFiles) { - parse(xmlFile); - } - - if (mFileNameToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) { - return false; - } - - PrintWriter writer = null; - try { - writer = new PrintWriter(outputFile); - - generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer); - - writer.flush(); - writer.close(); - return true; - } catch (FileNotFoundException | SecurityException e) { - Log.e(TAG, "Failed to generate " + outputFile, e); - - if (writer != null) { - writer.close(); - } - return false; - } - } - - private void parse(File xmlFile) { - if (xmlFile == null || !xmlFile.exists() || xmlFile.length() == 0) { - return; - } - - InputStreamReader in = null; - try { - if (xmlFile.getName().endsWith(".gz")) { - in = new InputStreamReader(new GZIPInputStream(new FileInputStream(xmlFile))); - } else { - in = new FileReader(xmlFile); - } - - parse(in, mFileNameToContentIdMap, mContentIdToFileContentMap); - - in.close(); - } catch (XmlPullParserException | IOException e) { - Log.e(TAG, "Failed to parse " + xmlFile, e); - if (in != null) { - try { - in.close(); - } catch (IOException ie) { - Log.w(TAG, "Failed to close " + xmlFile); - } - } - } - } - - /* - * Parses an input stream and fills a map from a file name to a content id for its license - * and a map from a content id to a license file content. - * - * Following xml format is expected from the input stream. - * - * - * file1 - * file2 - * ... - * license1 file contents - * license2 file contents - * ... - * - */ - @VisibleForTesting - static void parse(InputStreamReader in, Map outFileNameToContentIdMap, - Map outContentIdToFileContentMap) - throws XmlPullParserException, IOException { - Map fileNameToContentIdMap = new HashMap(); - Map contentIdToFileContentMap = new HashMap(); - - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(in); - parser.nextTag(); - - parser.require(XmlPullParser.START_TAG, "", TAG_ROOT); - - int state = parser.getEventType(); - while (state != XmlPullParser.END_DOCUMENT) { - if (state == XmlPullParser.START_TAG) { - if (TAG_FILE_NAME.equals(parser.getName())) { - String contentId = parser.getAttributeValue("", ATTR_CONTENT_ID); - if (!TextUtils.isEmpty(contentId)) { - String fileName = readText(parser).trim(); - if (!TextUtils.isEmpty(fileName)) { - fileNameToContentIdMap.put(fileName, contentId); - } - } - } else if (TAG_FILE_CONTENT.equals(parser.getName())) { - String contentId = parser.getAttributeValue("", ATTR_CONTENT_ID); - if (!TextUtils.isEmpty(contentId) && - !outContentIdToFileContentMap.containsKey(contentId) && - !contentIdToFileContentMap.containsKey(contentId)) { - String fileContent = readText(parser); - if (!TextUtils.isEmpty(fileContent)) { - contentIdToFileContentMap.put(contentId, fileContent); - } - } - } - } - - state = parser.next(); - } - outFileNameToContentIdMap.putAll(fileNameToContentIdMap); - outContentIdToFileContentMap.putAll(contentIdToFileContentMap); - } - - private static String readText(XmlPullParser parser) - throws IOException, XmlPullParserException { - StringBuffer result = new StringBuffer(); - int state = parser.next(); - while (state == XmlPullParser.TEXT) { - result.append(parser.getText()); - state = parser.next(); - } - return result.toString(); - } - - @VisibleForTesting - static void generateHtml(Map fileNameToContentIdMap, - Map contentIdToFileContentMap, PrintWriter writer) { - List fileNameList = new ArrayList(); - fileNameList.addAll(fileNameToContentIdMap.keySet()); - Collections.sort(fileNameList); - - writer.println(HTML_HEAD_STRING); - - int count = 0; - Map contentIdToOrderMap = new HashMap(); - List contentIdAndFileNamesList = new ArrayList(); - - // Prints all the file list with a link to its license file content. - for (String fileName : fileNameList) { - String contentId = fileNameToContentIdMap.get(fileName); - // Assigns an id to a newly referred license file content. - if (!contentIdToOrderMap.containsKey(contentId)) { - contentIdToOrderMap.put(contentId, count); - - // An index in contentIdAndFileNamesList is the order of each element. - contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId)); - count++; - } - - int id = contentIdToOrderMap.get(contentId); - contentIdAndFileNamesList.get(id).mFileNameList.add(fileName); - writer.format("
  • %s
  • \n", id, fileName); - } - - writer.println(HTML_MIDDLE_STRING); - - count = 0; - // Prints all contents of the license files in order of id. - for (ContentIdAndFileNames contentIdAndFileNames : contentIdAndFileNamesList) { - writer.format("\n", count); - writer.println("
    Notices for file(s):
    "); - writer.println("
    "); - for (String fileName : contentIdAndFileNames.mFileNameList) { - writer.format("%s
    \n", fileName); - } - writer.println("
    "); - writer.println("
    ");
    -            writer.println(contentIdToFileContentMap.get(
    -                    contentIdAndFileNames.mContentId));
    -            writer.println("
    "); - writer.println(""); - - count++; - } - - writer.println(HTML_REAR_STRING); - } -} diff --git a/src/com/android/settings/LicenseHtmlLoader.java b/src/com/android/settings/LicenseHtmlLoader.java deleted file mode 100644 index 97179269013..00000000000 --- a/src/com/android/settings/LicenseHtmlLoader.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings; - -import android.content.Context; -import android.support.annotation.VisibleForTesting; -import android.util.Log; - -import com.android.settings.utils.AsyncLoader; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * LicenseHtmlLoader is a loader which loads a license html file from default license xml files. - */ -class LicenseHtmlLoader extends AsyncLoader { - private static final String TAG = "LicenseHtmlLoader"; - - private static final String[] DEFAULT_LICENSE_XML_PATHS = { - "/system/etc/NOTICE.xml.gz", - "/vendor/etc/NOTICE.xml.gz", - "/odm/etc/NOTICE.xml.gz", - "/oem/etc/NOTICE.xml.gz"}; - private static final String NOTICE_HTML_FILE_NAME = "NOTICE.html"; - - private Context mContext; - - public LicenseHtmlLoader(Context context) { - super(context); - mContext = context; - } - - @Override - public File loadInBackground() { - return generateHtmlFromDefaultXmlFiles(); - } - - @Override - protected void onDiscardResult(File f) { - } - - private File generateHtmlFromDefaultXmlFiles() { - final List xmlFiles = getVaildXmlFiles(); - if (xmlFiles.isEmpty()) { - Log.e(TAG, "No notice file exists."); - return null; - } - - File cachedHtmlFile = getCachedHtmlFile(); - if(!isCachedHtmlFileOutdated(xmlFiles, cachedHtmlFile) || - generateHtmlFile(xmlFiles, cachedHtmlFile)) { - return cachedHtmlFile; - } - - return null; - } - - @VisibleForTesting - List getVaildXmlFiles() { - final List xmlFiles = new ArrayList(); - for (final String xmlPath : DEFAULT_LICENSE_XML_PATHS) { - File file = new File(xmlPath); - if (file.exists() && file.length() != 0) { - xmlFiles.add(file); - } - } - return xmlFiles; - } - - @VisibleForTesting - File getCachedHtmlFile() { - return new File(mContext.getCacheDir(), NOTICE_HTML_FILE_NAME); - } - - @VisibleForTesting - boolean isCachedHtmlFileOutdated(List xmlFiles, File cachedHtmlFile) { - boolean outdated = true; - if (cachedHtmlFile.exists() && cachedHtmlFile.length() != 0) { - outdated = false; - for (File file : xmlFiles) { - if (cachedHtmlFile.lastModified() < file.lastModified()) { - outdated = true; - break; - } - } - } - return outdated; - } - - @VisibleForTesting - boolean generateHtmlFile(List xmlFiles, File htmlFile) { - return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile); - } -} diff --git a/src/com/android/settings/SettingsLicenseActivity.java b/src/com/android/settings/SettingsLicenseActivity.java index 5b23a68990a..ebb1ae13afd 100644 --- a/src/com/android/settings/SettingsLicenseActivity.java +++ b/src/com/android/settings/SettingsLicenseActivity.java @@ -20,12 +20,10 @@ import android.app.Activity; import android.app.LoaderManager; import android.content.ActivityNotFoundException; import android.content.ContentResolver; -import android.content.Context; import android.content.Intent; import android.content.Loader; import android.net.Uri; import android.os.Bundle; -import android.os.StrictMode; import android.os.SystemProperties; import android.support.annotation.VisibleForTesting; import android.support.v4.content.FileProvider; @@ -34,10 +32,9 @@ import android.util.Log; import android.widget.Toast; import com.android.settings.users.RestrictedProfileSettings; +import com.android.settingslib.license.LicenseHtmlLoader; import java.io.File; -import java.util.ArrayList; -import java.util.List; /** * The "dialog" that shows from "License" in the Settings app. @@ -111,9 +108,9 @@ public class SettingsLicenseActivity extends Activity implements return; } showHtmlFromUri(Uri.fromFile(file)); - } + } - private void showHtmlFromUri(Uri uri) { + private void showHtmlFromUri(Uri uri) { // Kick off external viewer due to WebView security restrictions; we // carefully point it at HTMLViewer, since it offers to decompress // before viewing. diff --git a/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java b/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java index b39ec3b18b5..9ff96c1f0b6 100644 --- a/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java +++ b/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java @@ -24,9 +24,9 @@ import android.os.UserHandle; import android.util.Log; import com.android.internal.util.Preconditions; -import com.android.settings.utils.AsyncLoader; import com.android.settingslib.applications.StorageStatsSource; import com.android.settingslib.applications.StorageStatsSource.AppStorageStats; +import com.android.settingslib.utils.AsyncLoader; import java.io.IOException; diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionLoader.java b/src/com/android/settings/dashboard/suggestions/SuggestionLoader.java index b9d51ce04d6..8c5b46d09fe 100644 --- a/src/com/android/settings/dashboard/suggestions/SuggestionLoader.java +++ b/src/com/android/settings/dashboard/suggestions/SuggestionLoader.java @@ -20,7 +20,7 @@ import android.content.Context; import android.service.settings.suggestions.Suggestion; import android.util.Log; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; import java.util.List; diff --git a/src/com/android/settings/datausage/AppPrefLoader.java b/src/com/android/settings/datausage/AppPrefLoader.java index 30e30eb662f..b6848136868 100644 --- a/src/com/android/settings/datausage/AppPrefLoader.java +++ b/src/com/android/settings/datausage/AppPrefLoader.java @@ -21,7 +21,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.support.v7.preference.Preference; import android.util.ArraySet; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; public class AppPrefLoader extends AsyncLoader> { private ArraySet mPackages; diff --git a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java index 2ce53f65755..0b9b697f473 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java +++ b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java @@ -30,9 +30,9 @@ import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; -import com.android.settings.utils.AsyncLoader; import com.android.settings.wrapper.UserManagerWrapper; import com.android.settingslib.applications.StorageStatsSource; +import com.android.settingslib.utils.AsyncLoader; import com.android.settingslib.wrapper.PackageManagerWrapper; import java.io.IOException; diff --git a/src/com/android/settings/deviceinfo/storage/UserIconLoader.java b/src/com/android/settings/deviceinfo/storage/UserIconLoader.java index 4f00c3c5496..d1c29dfe38a 100644 --- a/src/com/android/settings/deviceinfo/storage/UserIconLoader.java +++ b/src/com/android/settings/deviceinfo/storage/UserIconLoader.java @@ -25,7 +25,7 @@ import android.util.SparseArray; import com.android.internal.util.Preconditions; import com.android.settings.Utils; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; /** * Fetches a user icon as a loader using a given icon loading lambda. diff --git a/src/com/android/settings/deviceinfo/storage/VolumeSizesLoader.java b/src/com/android/settings/deviceinfo/storage/VolumeSizesLoader.java index 720f1512b59..236f55f48b7 100644 --- a/src/com/android/settings/deviceinfo/storage/VolumeSizesLoader.java +++ b/src/com/android/settings/deviceinfo/storage/VolumeSizesLoader.java @@ -21,9 +21,9 @@ import android.content.Context; import android.os.storage.VolumeInfo; import android.support.annotation.VisibleForTesting; -import com.android.settings.utils.AsyncLoader; import com.android.settingslib.deviceinfo.PrivateStorageInfo; import com.android.settingslib.deviceinfo.StorageVolumeProvider; +import com.android.settingslib.utils.AsyncLoader; import java.io.IOException; diff --git a/src/com/android/settings/fuelgauge/BatteryInfoLoader.java b/src/com/android/settings/fuelgauge/BatteryInfoLoader.java index ce22a8cf03f..614eb8006e2 100644 --- a/src/com/android/settings/fuelgauge/BatteryInfoLoader.java +++ b/src/com/android/settings/fuelgauge/BatteryInfoLoader.java @@ -25,7 +25,7 @@ import android.os.BatteryStats; import android.os.SystemClock; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; /** * Loader that can be used by classes to load BatteryInfo in a background thread. This loader will diff --git a/src/com/android/settings/fuelgauge/BatteryStatsHelperLoader.java b/src/com/android/settings/fuelgauge/BatteryStatsHelperLoader.java index b81f2823b88..28585ae0b6a 100644 --- a/src/com/android/settings/fuelgauge/BatteryStatsHelperLoader.java +++ b/src/com/android/settings/fuelgauge/BatteryStatsHelperLoader.java @@ -23,7 +23,7 @@ import android.os.UserManager; import android.support.annotation.VisibleForTesting; import com.android.internal.os.BatteryStatsHelper; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; /** * Loader to get new {@link BatteryStatsHelper} in the background diff --git a/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java b/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java index 5f4758a40b7..19aa6390393 100644 --- a/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java +++ b/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java @@ -22,7 +22,7 @@ import android.os.BatteryStats; import android.os.SystemClock; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; import java.util.ArrayList; import java.util.List; diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java index 5f46b074b90..b811f208b84 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageBase.java +++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java @@ -26,7 +26,7 @@ import android.view.Menu; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; /** * Common base class for things that need to show the battery usage graph. diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java b/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java index 596eaf5980e..f26b7426e47 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalyLoader.java @@ -26,7 +26,7 @@ import android.util.Log; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.util.ArrayUtils; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/src/com/android/settings/search/SavedQueryLoader.java b/src/com/android/settings/search/SavedQueryLoader.java index e8efe85f78d..5df3610354f 100644 --- a/src/com/android/settings/search/SavedQueryLoader.java +++ b/src/com/android/settings/search/SavedQueryLoader.java @@ -23,7 +23,7 @@ import android.database.sqlite.SQLiteDatabase; import android.support.annotation.VisibleForTesting; import com.android.settings.search.IndexDatabaseHelper.SavedQueriesColumns; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; import java.util.ArrayList; import java.util.List; diff --git a/src/com/android/settings/search/SavedQueryRecorder.java b/src/com/android/settings/search/SavedQueryRecorder.java index 466af0b4716..b3b0bb80506 100644 --- a/src/com/android/settings/search/SavedQueryRecorder.java +++ b/src/com/android/settings/search/SavedQueryRecorder.java @@ -24,7 +24,7 @@ import android.database.sqlite.SQLiteException; import android.util.Log; import com.android.settings.search.IndexDatabaseHelper; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES; diff --git a/src/com/android/settings/search/SavedQueryRemover.java b/src/com/android/settings/search/SavedQueryRemover.java index 77334a5ab55..c6abe978f65 100644 --- a/src/com/android/settings/search/SavedQueryRemover.java +++ b/src/com/android/settings/search/SavedQueryRemover.java @@ -24,7 +24,7 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.util.Log; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; public class SavedQueryRemover extends AsyncLoader { diff --git a/src/com/android/settings/search/SearchResultLoader.java b/src/com/android/settings/search/SearchResultLoader.java index 7ec3146171a..f4abd8e40b9 100644 --- a/src/com/android/settings/search/SearchResultLoader.java +++ b/src/com/android/settings/search/SearchResultLoader.java @@ -1,6 +1,6 @@ package com.android.settings.search; -import com.android.settings.utils.AsyncLoader; +import com.android.settingslib.utils.AsyncLoader; import android.content.Context; diff --git a/src/com/android/settings/utils/AsyncLoader.java b/src/com/android/settings/utils/AsyncLoader.java deleted file mode 100644 index 76c99fa4793..00000000000 --- a/src/com/android/settings/utils/AsyncLoader.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2016 Google Inc. - * Licensed to The Android Open Source Project. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.utils; - -import android.content.AsyncTaskLoader; -import android.content.Context; - -/** - * This class fills in some boilerplate for AsyncTaskLoader to actually load things. - * - * Subclasses need to implement {@link AsyncLoader#loadInBackground()} to perform the actual - * background task, and {@link AsyncLoader#onDiscardResult(T)} to clean up previously loaded - * results. - * - * This loader is based on the MailAsyncTaskLoader from the AOSP EmailUnified repo. - */ -public abstract class AsyncLoader extends AsyncTaskLoader { - private T mResult; - - public AsyncLoader(final Context context) { - super(context); - } - - @Override - protected void onStartLoading() { - if (mResult != null) { - deliverResult(mResult); - } - - if (takeContentChanged() || mResult == null) { - forceLoad(); - } - } - - @Override - protected void onStopLoading() { - cancelLoad(); - } - - @Override - public void deliverResult(final T data) { - if (isReset()) { - if (data != null) { - onDiscardResult(data); - } - return; - } - - final T oldResult = mResult; - mResult = data; - - if (isStarted()) { - super.deliverResult(data); - } - - if (oldResult != null && oldResult != mResult) { - onDiscardResult(oldResult); - } - } - - @Override - protected void onReset() { - super.onReset(); - - onStopLoading(); - - if (mResult != null) { - onDiscardResult(mResult); - } - mResult = null; - } - - @Override - public void onCanceled(final T data) { - super.onCanceled(data); - - if (data != null) { - onDiscardResult(data); - } - } - - /** - * Called when discarding the load results so subclasses can take care of clean-up or - * recycling tasks. This is not called if the same result (by way of pointer equality) is - * returned again by a subsequent call to loadInBackground, or if result is null. - * - * Note that this may be called concurrently with loadInBackground(), and in some circumstances - * may be called more than once for a given object. - * - * @param result The value returned from {@link AsyncLoader#loadInBackground()} which - * is to be discarded. - */ - protected abstract void onDiscardResult(final T result); -} diff --git a/tests/robotests/src/com/android/settings/LicenseHtmlGeneratorFromXmlTest.java b/tests/robotests/src/com/android/settings/LicenseHtmlGeneratorFromXmlTest.java deleted file mode 100644 index ea4b2726aed..00000000000 --- a/tests/robotests/src/com/android/settings/LicenseHtmlGeneratorFromXmlTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings; - -import static com.google.common.truth.Truth.assertThat; - -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import java.util.HashMap; -import java.util.Map; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.annotation.Config; -import org.xmlpull.v1.XmlPullParserException; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class LicenseHtmlGeneratorFromXmlTest { - private static final String VAILD_XML_STRING = - "\n" + - "\n" + - "/file0\n" + - "/file1\n" + - "\n" + - ""; - - private static final String INVAILD_XML_STRING = - "\n" + - "\n" + - "/file0\n" + - "/file1\n" + - "\n" + - ""; - - private static final String EXPECTED_HTML_STRING = - "\n" + - "\n" + - "" + - "\n" + - "
    \n" + - "\n" + - "
    \n" + - "\n" + - "\n" + - "
    \n" + - "
    Notices for file(s):
    \n" + - "
    \n" + - "/file0
    \n" + - "/file1
    \n" + - "
    \n" + - "
    \n" +
    -            "license content #0\n" +
    -            "
    \n" + - "
    \n"; - - @Test - public void testParseValidXmlStream() throws XmlPullParserException, IOException { - Map fileNameToContentIdMap = new HashMap(); - Map contentIdToFileContentMap = new HashMap(); - - LicenseHtmlGeneratorFromXml.parse( - new InputStreamReader(new ByteArrayInputStream(VAILD_XML_STRING.getBytes())), - fileNameToContentIdMap, contentIdToFileContentMap); - assertThat(fileNameToContentIdMap.size()).isEqualTo(2); - assertThat(fileNameToContentIdMap.get("/file0")).isEqualTo("0"); - assertThat(fileNameToContentIdMap.get("/file1")).isEqualTo("0"); - assertThat(contentIdToFileContentMap.size()).isEqualTo(1); - assertThat(contentIdToFileContentMap.get("0")).isEqualTo("license content #0"); - } - - @Test(expected = XmlPullParserException.class) - public void testParseInvalidXmlStream() throws XmlPullParserException, IOException { - Map fileNameToContentIdMap = new HashMap(); - Map contentIdToFileContentMap = new HashMap(); - - LicenseHtmlGeneratorFromXml.parse( - new InputStreamReader(new ByteArrayInputStream(INVAILD_XML_STRING.getBytes())), - fileNameToContentIdMap, contentIdToFileContentMap); - } - - @Test - public void testGenerateHtml() { - Map fileNameToContentIdMap = new HashMap(); - Map contentIdToFileContentMap = new HashMap(); - - fileNameToContentIdMap.put("/file0", "0"); - fileNameToContentIdMap.put("/file1", "0"); - contentIdToFileContentMap.put("0", "license content #0"); - - StringWriter output = new StringWriter(); - LicenseHtmlGeneratorFromXml.generateHtml( - fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output)); - assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING); - } -} diff --git a/tests/robotests/src/com/android/settings/LicenseHtmlLoaderTest.java b/tests/robotests/src/com/android/settings/LicenseHtmlLoaderTest.java deleted file mode 100644 index b16d3155532..00000000000 --- a/tests/robotests/src/com/android/settings/LicenseHtmlLoaderTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -import android.content.Context; - -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import java.io.File; -import java.util.ArrayList; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class LicenseHtmlLoaderTest { - @Mock - private Context mContext; - - LicenseHtmlLoader newLicenseHtmlLoader(ArrayList xmlFiles, - File cachedHtmlFile, boolean isCachedHtmlFileOutdated, - boolean generateHtmlFileSucceeded) { - LicenseHtmlLoader loader = spy(new LicenseHtmlLoader(mContext)); - doReturn(xmlFiles).when(loader).getVaildXmlFiles(); - doReturn(cachedHtmlFile).when(loader).getCachedHtmlFile(); - doReturn(isCachedHtmlFileOutdated).when(loader).isCachedHtmlFileOutdated(any(), any()); - doReturn(generateHtmlFileSucceeded).when(loader).generateHtmlFile(any(), any()); - return loader; - } - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testLoadInBackground() { - ArrayList xmlFiles = new ArrayList(); - xmlFiles.add(new File("test.xml")); - File cachedHtmlFile = new File("test.html"); - - LicenseHtmlLoader loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true, true); - - assertThat(loader.loadInBackground()).isEqualTo(cachedHtmlFile); - verify(loader).generateHtmlFile(any(), any()); - } - - @Test - public void testLoadInBackgroundWithNoVaildXmlFiles() { - ArrayList xmlFiles = new ArrayList(); - File cachedHtmlFile = new File("test.html"); - - LicenseHtmlLoader loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true, true); - - assertThat(loader.loadInBackground()).isNull(); - verify(loader, never()).generateHtmlFile(any(), any()); - } - - @Test - public void testLoadInBackgroundWithNonOutdatedCachedHtmlFile() { - ArrayList xmlFiles = new ArrayList(); - xmlFiles.add(new File("test.xml")); - File cachedHtmlFile = new File("test.html"); - - LicenseHtmlLoader loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, false, true); - - assertThat(loader.loadInBackground()).isEqualTo(cachedHtmlFile); - verify(loader, never()).generateHtmlFile(any(), any()); - } - - @Test - public void testLoadInBackgroundWithGenerateHtmlFileFailed() { - ArrayList xmlFiles = new ArrayList(); - xmlFiles.add(new File("test.xml")); - File cachedHtmlFile = new File("test.html"); - - LicenseHtmlLoader loader = newLicenseHtmlLoader(xmlFiles, cachedHtmlFile, true, false); - - assertThat(loader.loadInBackground()).isNull(); - verify(loader).generateHtmlFile(any(), any()); - } -} diff --git a/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java b/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java index ecda97edc46..aceb671213e 100644 --- a/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java +++ b/tests/robotests/src/com/android/settings/SettingsLicenseActivityTest.java @@ -18,21 +18,19 @@ package com.android.settings; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.robolectric.Shadows.shadowOf; import android.app.Application; -import android.os.SystemProperties; import android.content.Intent; import android.net.Uri; +import android.os.SystemProperties; import com.android.settings.testutils.SettingsRobolectricTestRunner; -import java.io.File; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -42,6 +40,8 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.android.controller.ActivityController; import org.robolectric.annotation.Config; +import java.io.File; + @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SettingsLicenseActivityTest { From b000ace0eb50c32f290cf31f14a52c3f3c3906e0 Mon Sep 17 00:00:00 2001 From: Jaekyun Seok Date: Thu, 7 Dec 2017 19:46:41 +0900 Subject: [PATCH 04/13] Fix failure of ZenModeAutomaticRulesPreferenceControllerTest Running ZenModeAutomaticRulesPreferenceControllerTest fails due to missing field "DEFAULT_RULE_IDS". "mDefaultRuleIds" should be used instead of it. Bug: 63077372 Test: make \ ROBOTEST_FILTER=ZenModeAutomaticRulesPreferenceControllerTest \ RunSettingsRoboTests Change-Id: Ieb4a4304a0404685e4a50eb3a5c863a0132ebf7d --- .../ZenModeAutomaticRulesPreferenceControllerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java index 1b10e85db90..20f9e62802c 100644 --- a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java @@ -82,7 +82,7 @@ public class ZenModeAutomaticRulesPreferenceControllerTest { mock(Lifecycle.class)); ReflectionHelpers.setField(mController, "mBackend", mBackend); - ReflectionHelpers.setField(mController, "DEFAULT_RULE_IDS", mDefaultIds); + ReflectionHelpers.setField(mController, "mDefaultRuleIds", mDefaultIds); when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn( mockPref); @@ -188,4 +188,4 @@ public class ZenModeAutomaticRulesPreferenceControllerTest { return ruleMap; } -} \ No newline at end of file +} From 1aabe820e892f9ed61d58b0d31a0fdfcb6d904db Mon Sep 17 00:00:00 2001 From: Beverly Date: Thu, 7 Dec 2017 10:04:20 -0500 Subject: [PATCH 05/13] Fix ZenModeScheduleRuleSettingsTest null pointer Test: make ROBOTEST_FILTER=ZenModeScheduleRuleSettingsTest RunSettingsRoboTests -j40 Bug: 63077372 Change-Id: Ib843337e5867507eec1236fb4504035c151c348c --- .../ZenModeScheduleRuleSettingsTest.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeScheduleRuleSettingsTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeScheduleRuleSettingsTest.java index f8cc7672b9b..070aa386a1a 100644 --- a/tests/robotests/src/com/android/settings/notification/ZenModeScheduleRuleSettingsTest.java +++ b/tests/robotests/src/com/android/settings/notification/ZenModeScheduleRuleSettingsTest.java @@ -17,10 +17,10 @@ package com.android.settings.notification; import android.app.Activity; +import android.app.NotificationManager; import android.content.Context; import android.content.res.Resources; import android.content.Intent; -import android.os.UserManager; import com.android.settings.R; import com.android.settings.TestConfig; @@ -34,6 +34,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowToast; +import org.robolectric.shadows.ShadowApplication; +import org.robolectric.RuntimeEnvironment; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; @@ -58,14 +60,19 @@ public class ZenModeScheduleRuleSettingsTest { private Intent mIntent; @Mock - private UserManager mUserManager; + private NotificationManager mNotificationManager; private TestFragment mFragment; + private Context mContext; @Before public void setUp() { MockitoAnnotations.initMocks(this); + ShadowApplication shadowApplication = ShadowApplication.getInstance(); + shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager); + mContext = shadowApplication.getApplicationContext(); + mFragment = spy(new TestFragment()); mFragment.onAttach(application); @@ -77,13 +84,13 @@ public class ZenModeScheduleRuleSettingsTest { when(mActivity.getTheme()).thenReturn(res.newTheme()); when(mActivity.getIntent()).thenReturn(mIntent); when(mActivity.getResources()).thenReturn(res); - when(mFragment.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + when(mFragment.getContext()).thenReturn(mContext); } @Test public void onCreate_noRuleId_shouldToastAndFinishAndNoCrash() { - final Context ctx = application.getApplicationContext(); - final String expected = ctx.getResources().getString(R.string.zen_mode_rule_not_found_text); + final String expected = mContext.getResources().getString( + R.string.zen_mode_rule_not_found_text); mFragment.onCreate(null); @@ -93,7 +100,7 @@ public class ZenModeScheduleRuleSettingsTest { // verify the finish verify(mActivity).finish(); - //shoud not crash + //should not crash } public static class TestFragment extends ZenModeScheduleRuleSettings { From 1949600132d05da7e3785412b7fd8fc336c8205b Mon Sep 17 00:00:00 2001 From: Maggie Date: Thu, 30 Nov 2017 10:50:50 -0800 Subject: [PATCH 06/13] Send MODE_CHANGING broadcast before location mode change. When location mode is about to change in Settings app, send MODE_CHANGING broadcast. Fixes: 28057031 Test: manual Test: robotests Change-Id: I430941915daedf13e7b5d22dc8a6e37729d95b75 --- .../settings/location/LocationEnabler.java | 19 ++++------------- .../location/LocationEnablerTest.java | 21 +++++++++++-------- ...deRadioButtonPreferenceControllerTest.java | 11 +++++----- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/com/android/settings/location/LocationEnabler.java b/src/com/android/settings/location/LocationEnabler.java index 0bec6ba1f0d..5c5399ceff9 100644 --- a/src/com/android/settings/location/LocationEnabler.java +++ b/src/com/android/settings/location/LocationEnabler.java @@ -13,6 +13,7 @@ */ package com.android.settings.location; +import android.app.ActivityManager; import android.Manifest.permission; import android.content.BroadcastReceiver; import android.content.Context; @@ -32,6 +33,8 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnResume; +import static com.android.settingslib.Utils.updateLocationMode; + /** * A class that listens to location settings change and modifies location settings * settings. @@ -40,11 +43,6 @@ public class LocationEnabler implements LifecycleObserver, OnResume, OnPause { private static final String TAG = "LocationEnabler"; @VisibleForTesting - static final String MODE_CHANGING_ACTION = - "com.android.settings.location.MODE_CHANGING"; - private static final String CURRENT_MODE_KEY = "CURRENT_MODE"; - private static final String NEW_MODE_KEY = "NEW_MODE"; - @VisibleForTesting static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED = new IntentFilter(LocationManager.MODE_CHANGED_ACTION); @@ -122,7 +120,7 @@ public class LocationEnabler implements LifecycleObserver, OnResume, OnPause { return; } - updateLocationMode(currentMode, mode); + updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser()); refreshLocationMode(); } @@ -154,13 +152,4 @@ public class LocationEnabler implements LifecycleObserver, OnResume, OnPause { private boolean isRestricted() { return mUserManager.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION); } - - private boolean updateLocationMode(int oldMode, int newMode) { - final Intent intent = new Intent(MODE_CHANGING_ACTION); - intent.putExtra(CURRENT_MODE_KEY, oldMode); - intent.putExtra(NEW_MODE_KEY, newMode); - mContext.sendBroadcast(intent, permission.WRITE_SECURE_SETTINGS); - return Settings.Secure.putInt( - mContext.getContentResolver(), Settings.Secure.LOCATION_MODE, newMode); - } } diff --git a/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java b/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java index 25e491a2b17..1e5077067b7 100644 --- a/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java +++ b/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java @@ -16,9 +16,7 @@ package com.android.settings.location; import static android.Manifest.permission.WRITE_SECURE_SETTINGS; - import static com.google.common.truth.Truth.assertThat; - import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -31,18 +29,21 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; +import android.location.LocationManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; - import com.android.settings.TestConfig; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowSecureSettings; import com.android.settingslib.core.lifecycle.Lifecycle; - +import java.util.ArrayList; +import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -52,11 +53,10 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; -import java.util.ArrayList; -import java.util.List; - @RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +@Config(manifest = TestConfig.MANIFEST_PATH, + sdk = TestConfig.SDK_VERSION, + shadows = {ShadowSecureSettings.class}) public class LocationEnablerTest { @Mock @@ -178,8 +178,11 @@ public class LocationEnablerTest { mEnabler.setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY); - verify(mContext).sendBroadcast(argThat(actionMatches(mEnabler.MODE_CHANGING_ACTION)), + verify(mContext).sendBroadcastAsUser( + argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)), + eq(UserHandle.of(ActivityManager.getCurrentUser())), eq(WRITE_SECURE_SETTINGS)); + } @Test diff --git a/tests/robotests/src/com/android/settings/location/LocationModeRadioButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationModeRadioButtonPreferenceControllerTest.java index 0c7ac41c0df..ae98acc0c5e 100644 --- a/tests/robotests/src/com/android/settings/location/LocationModeRadioButtonPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/location/LocationModeRadioButtonPreferenceControllerTest.java @@ -16,29 +16,30 @@ package com.android.settings.location; import static com.google.common.truth.Truth.assertThat; - import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.provider.Settings; import android.support.v7.preference.PreferenceScreen; - import com.android.settings.TestConfig; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.ShadowSecureSettings; import com.android.settings.widget.RadioButtonPreference; import com.android.settingslib.core.lifecycle.Lifecycle; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; @RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +@Config( + manifest = TestConfig.MANIFEST_PATH, + sdk = TestConfig.SDK_VERSION, + shadows = {ShadowSecureSettings.class}) public class LocationModeRadioButtonPreferenceControllerTest { @Mock From 765007b0bfb2f27707e2394b597d208f8e512bb8 Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Fri, 1 Dec 2017 17:18:01 -0800 Subject: [PATCH 07/13] Add controllers for default app shortcut preferences. - add the default app shortcut preferences to the preference screen xml instead of creating them dynamically in the fragment. - add controller for each of the shortcut preference. - move the corresponding shortcut detail settings into the appinfo package. - add individual preference screen xml for the shortcut detail settings instead of using the shared screen template. Bug: 69384089 Test: make RunSettingsRoboTests Change-Id: I7bc0b3b727e87fb1a32a82291e64b8e290947671 --- res/xml/app_info_settings.xml | 27 +++ res/xml/draw_overlay_permissions_details.xml | 33 ++++ res/xml/external_sources_details.xml | 1 - ...picture_in_picture_permissions_details.xml | 29 +++ ...te_system_settings_permissions_details.xml | 33 ++++ .../AppInfoDashboardFragment.java | 170 +++--------------- .../AppStateInstallAppsBridge.java | 2 +- .../applications/InstalledAppDetails.java | 5 + ...DrawOverlayDetailPreferenceController.java | 70 ++++++++ .../{ => appinfo}/DrawOverlayDetails.java | 30 ++-- ...ernalSourceDetailPreferenceController.java | 71 ++++++++ .../{ => appinfo}/ExternalSourcesDetails.java | 4 +- ...reInPictureDetailPreferenceController.java | 86 +++++++++ .../PictureInPictureDetails.java | 24 +-- .../PictureInPictureSettings.java | 5 +- .../{ => appinfo}/WriteSettingsDetails.java | 25 +-- ...iteSystemSettingsPreferenceController.java | 71 ++++++++ .../ManageApplications.java | 6 +- .../core/gateway/SettingsGateway.java | 10 +- .../grandfather_not_implementing_indexable | 10 +- ...OverlayDetailPreferenceControllerTest.java | 120 +++++++++++++ .../{ => appinfo}/DrawOverlayDetailsTest.java | 2 +- ...lSourceDetailPreferenceControllerTest.java | 105 +++++++++++ ...PictureDetailPreferenceControllerTest.java | 107 +++++++++++ .../PictureInPictureDetailsTest.java | 2 +- .../PictureInPictureSettingsTest.java | 2 +- .../WriteSettingsDetailsTest.java | 2 +- ...ystemSettingsPreferenceControllerTest.java | 120 +++++++++++++ 28 files changed, 961 insertions(+), 211 deletions(-) create mode 100644 res/xml/draw_overlay_permissions_details.xml create mode 100644 res/xml/picture_in_picture_permissions_details.xml create mode 100644 res/xml/write_system_settings_permissions_details.xml create mode 100644 src/com/android/settings/applications/appinfo/DrawOverlayDetailPreferenceController.java rename src/com/android/settings/applications/{ => appinfo}/DrawOverlayDetails.java (90%) create mode 100644 src/com/android/settings/applications/appinfo/ExternalSourceDetailPreferenceController.java rename src/com/android/settings/applications/{ => appinfo}/ExternalSourcesDetails.java (96%) create mode 100644 src/com/android/settings/applications/appinfo/PictureInPictureDetailPreferenceController.java rename src/com/android/settings/applications/{ => appinfo}/PictureInPictureDetails.java (81%) rename src/com/android/settings/applications/{ => appinfo}/PictureInPictureSettings.java (97%) rename src/com/android/settings/applications/{ => appinfo}/WriteSettingsDetails.java (90%) create mode 100644 src/com/android/settings/applications/appinfo/WriteSystemSettingsPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/applications/appinfo/DrawOverlayDetailPreferenceControllerTest.java rename tests/robotests/src/com/android/settings/applications/{ => appinfo}/DrawOverlayDetailsTest.java (98%) create mode 100644 tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourceDetailPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureDetailPreferenceControllerTest.java rename tests/robotests/src/com/android/settings/applications/{ => appinfo}/PictureInPictureDetailsTest.java (98%) rename tests/robotests/src/com/android/settings/applications/{ => appinfo}/PictureInPictureSettingsTest.java (99%) rename tests/robotests/src/com/android/settings/applications/{ => appinfo}/WriteSettingsDetailsTest.java (97%) create mode 100644 tests/robotests/src/com/android/settings/applications/appinfo/WriteSystemSettingsPreferenceControllerTest.java diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml index e2fb2e44d30..664210be1c3 100644 --- a/res/xml/app_info_settings.xml +++ b/res/xml/app_info_settings.xml @@ -105,6 +105,33 @@ android:title="@string/sms_application_title" android:summary="@string/summary_placeholder" /> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/xml/external_sources_details.xml b/res/xml/external_sources_details.xml index 9e79c107a6a..ea2abdc52bc 100644 --- a/res/xml/external_sources_details.xml +++ b/res/xml/external_sources_details.xml @@ -15,7 +15,6 @@ --> + + + + + + + + + diff --git a/res/xml/write_system_settings_permissions_details.xml b/res/xml/write_system_settings_permissions_details.xml new file mode 100644 index 00000000000..39d6983353d --- /dev/null +++ b/res/xml/write_system_settings_permissions_details.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/src/com/android/settings/applications/AppInfoDashboardFragment.java b/src/com/android/settings/applications/AppInfoDashboardFragment.java index a725781cc2a..d7d91f3f717 100755 --- a/src/com/android/settings/applications/AppInfoDashboardFragment.java +++ b/src/com/android/settings/applications/AppInfoDashboardFragment.java @@ -18,7 +18,6 @@ package com.android.settings.applications; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; -import android.Manifest.permission; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; @@ -47,7 +46,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; -import android.support.v7.preference.Preference.OnPreferenceClickListener; import android.support.v7.preference.PreferenceCategory; import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; @@ -58,7 +56,6 @@ import android.view.MenuItem; import android.view.View; import android.webkit.IWebViewUpdateService; -import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.DeviceAdminAdd; import com.android.settings.R; @@ -78,11 +75,10 @@ import com.android.settings.applications.appinfo.DefaultEmergencyShortcutPrefere import com.android.settings.applications.appinfo.DefaultHomeShortcutPreferenceController; import com.android.settings.applications.appinfo.DefaultPhoneShortcutPreferenceController; import com.android.settings.applications.appinfo.DefaultSmsShortcutPreferenceController; -import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController; -import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController; -import com.android.settings.applications.defaultapps.DefaultHomePreferenceController; -import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController; -import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController; +import com.android.settings.applications.appinfo.DrawOverlayDetailPreferenceController; +import com.android.settings.applications.appinfo.ExternalSourceDetailPreferenceController; +import com.android.settings.applications.appinfo.PictureInPictureDetailPreferenceController; +import com.android.settings.applications.appinfo.WriteSystemSettingsPreferenceController; import com.android.settings.applications.instantapps.InstantAppButtonsController; import com.android.settings.applications.manageapplications.ManageApplications; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; @@ -90,6 +86,7 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.EntityHeaderController; +import com.android.settings.widget.PreferenceCategoryController; import com.android.settings.wrapper.DevicePolicyManagerWrapper; import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.applications.AppUtils; @@ -97,7 +94,6 @@ import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.wrapper.PackageManagerWrapper; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -149,6 +145,7 @@ public class AppInfoDashboardFragment extends DashboardFragment public static final String ARG_PACKAGE_UID = "uid"; protected static final boolean localLOGV = false; + private static final String KEY_ADVANCED_APP_INFO_CATEGORY = "advanced_app_info"; private EnforcedAdmin mAppsControlDisallowedAdmin; private boolean mAppsControlDisallowedBySystem; @@ -358,11 +355,6 @@ public class AppInfoDashboardFragment extends DashboardFragment if (!refreshUi()) { setIntentAndFinish(true, true); } - - if (mFinishing) { - return; - } - updateDynamicPrefs(); } @Override @@ -404,6 +396,17 @@ public class AppInfoDashboardFragment extends DashboardFragment controllers.add(new DefaultEmergencyShortcutPreferenceController(context, packageName)); controllers.add(new DefaultSmsShortcutPreferenceController(context, packageName)); + final List advancedAppInfoControllers = new ArrayList<>(); + advancedAppInfoControllers.add(new DrawOverlayDetailPreferenceController(context, this)); + advancedAppInfoControllers.add(new WriteSystemSettingsPreferenceController(context, this)); + advancedAppInfoControllers.add( + new PictureInPictureDetailPreferenceController(context, this, packageName)); + advancedAppInfoControllers.add( + new ExternalSourceDetailPreferenceController(context, this, packageName)); + controllers.addAll(advancedAppInfoControllers); + controllers.add(new PreferenceCategoryController( + context, KEY_ADVANCED_APP_INFO_CATEGORY, advancedAppInfoControllers)); + return controllers; } @@ -415,6 +418,9 @@ public class AppInfoDashboardFragment extends DashboardFragment } public PackageInfo getPackageInfo() { + if (mAppEntry == null) { + retrieveAppEntry(); + } return mPackageInfo; } @@ -603,7 +609,8 @@ public class AppInfoDashboardFragment extends DashboardFragment return false; } - protected boolean refreshUi() { + @VisibleForTesting + boolean refreshUi() { retrieveAppEntry(); if (mAppEntry == null) { return false; // onCreate must have failed, make sure to exit @@ -782,10 +789,6 @@ public class AppInfoDashboardFragment extends DashboardFragment } } - private void startAppInfoFragment(Class fragment, int title) { - startAppInfoFragment(fragment, title, this, mAppEntry); - } - public static void startAppInfoFragment(Class fragment, int title, SettingsPreferenceFragment caller, AppEntry appEntry) { // start new fragment to display extended information @@ -871,100 +874,10 @@ public class AppInfoDashboardFragment extends DashboardFragment if (UserManager.get(getContext()).isManagedProfile()) { return; } - final PreferenceScreen screen = getPreferenceScreen(); - final Context context = getContext(); - - // Get the package info with the activities - PackageInfo packageInfoWithActivities = null; - try { - packageInfoWithActivities = mPm.getPackageInfoAsUser(mPackageName, - PackageManager.GET_ACTIVITIES, UserHandle.myUserId()); - } catch (NameNotFoundException e) { - Log.e(TAG, "Exception while retrieving the package info of " + mPackageName, e); - } - - boolean hasDrawOverOtherApps = hasPermission(permission.SYSTEM_ALERT_WINDOW); - boolean hasWriteSettings = hasPermission(permission.WRITE_SETTINGS); - boolean hasPictureInPictureActivities = (packageInfoWithActivities != null) && - PictureInPictureSettings.checkPackageHasPictureInPictureActivities( - packageInfoWithActivities.packageName, - packageInfoWithActivities.activities); - boolean isPotentialAppSource = isPotentialAppSource(); - if (hasDrawOverOtherApps || hasWriteSettings || hasPictureInPictureActivities || - isPotentialAppSource) { - PreferenceCategory category = new PreferenceCategory(getPrefContext()); - category.setTitle(R.string.advanced_apps); - screen.addPreference(category); - - if (hasDrawOverOtherApps) { - Preference pref = new Preference(getPrefContext()); - pref.setTitle(R.string.draw_overlay); - pref.setKey("system_alert_window"); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - startAppInfoFragment(DrawOverlayDetails.class, R.string.draw_overlay); - return true; - } - }); - category.addPreference(pref); - } - if (hasWriteSettings) { - Preference pref = new Preference(getPrefContext()); - pref.setTitle(R.string.write_settings); - pref.setKey("write_settings_apps"); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - startAppInfoFragment(WriteSettingsDetails.class, R.string.write_settings); - return true; - } - }); - category.addPreference(pref); - } - if (hasPictureInPictureActivities) { - Preference pref = new Preference(getPrefContext()); - pref.setTitle(R.string.picture_in_picture_app_detail_title); - pref.setKey("picture_in_picture"); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - AppInfoBase.startAppInfoFragment(PictureInPictureDetails.class, - R.string.picture_in_picture_app_detail_title, mPackageName, - mPackageInfo.applicationInfo.uid, AppInfoDashboardFragment.this, - -1, getMetricsCategory()); - return true; - } - }); - category.addPreference(pref); - } - if (isPotentialAppSource) { - Preference pref = new Preference(getPrefContext()); - pref.setTitle(R.string.install_other_apps); - pref.setKey("install_other_apps"); - pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - startAppInfoFragment(ExternalSourcesDetails.class, - R.string.install_other_apps); - return true; - } - }); - category.addPreference(pref); - } - } - - addAppInstallerInfoPref(screen); + addAppInstallerInfoPref(getPreferenceScreen()); maybeAddInstantAppButtons(); } - private boolean isPotentialAppSource() { - AppStateInstallAppsBridge.InstallAppsState appState = - new AppStateInstallAppsBridge(getContext(), null, null) - .createInstallAppsStateFor(mPackageName, mPackageInfo.applicationInfo.uid); - return appState.isPotentialAppSource(); - } - private void addAppInstallerInfoPref(PreferenceScreen screen) { String installerPackageName = AppStoreUtil.getInstallerPackageName(getContext(), mPackageName); @@ -1008,39 +921,6 @@ public class AppInfoDashboardFragment extends DashboardFragment } } - private boolean hasPermission(String permission) { - if (mPackageInfo == null || mPackageInfo.requestedPermissions == null) { - return false; - } - for (int i = 0; i < mPackageInfo.requestedPermissions.length; i++) { - if (mPackageInfo.requestedPermissions[i].equals(permission)) { - return true; - } - } - return false; - } - - private void updateDynamicPrefs() { - final Context context = getContext(); - Preference pref = findPreference("system_alert_window"); - if (pref != null) { - pref.setSummary(DrawOverlayDetails.getSummary(getContext(), mAppEntry)); - } - pref = findPreference("picture_in_picture"); - if (pref != null) { - pref.setSummary(PictureInPictureDetails.getPreferenceSummary(getContext(), - mPackageInfo.applicationInfo.uid, mPackageName)); - } - pref = findPreference("write_settings_apps"); - if (pref != null) { - pref.setSummary(WriteSettingsDetails.getSummary(getContext(), mAppEntry)); - } - pref = findPreference("install_other_apps"); - if (pref != null) { - pref.setSummary(ExternalSourcesDetails.getPreferenceSummary(getContext(), mAppEntry)); - } - } - private void onPackageRemoved() { getActivity().finishActivity(SUB_INFO_FRAGMENT); getActivity().finishAndRemoveTask(); @@ -1112,7 +992,7 @@ public class AppInfoDashboardFragment extends DashboardFragment return mPackageName; } final Bundle args = getArguments(); - String mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null; + mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null; if (mPackageName == null) { Intent intent = (args == null) ? getActivity().getIntent() : (Intent) args.getParcelable("intent"); @@ -1229,7 +1109,7 @@ public class AppInfoDashboardFragment extends DashboardFragment @Override public int getMetricsCategory() { - return MetricsProto.MetricsEvent.DIALOG_APP_INFO_ACTION; + return MetricsEvent.DIALOG_APP_INFO_ACTION; } @Override diff --git a/src/com/android/settings/applications/AppStateInstallAppsBridge.java b/src/com/android/settings/applications/AppStateInstallAppsBridge.java index 0c3582e623c..5b9ded648cf 100644 --- a/src/com/android/settings/applications/AppStateInstallAppsBridge.java +++ b/src/com/android/settings/applications/AppStateInstallAppsBridge.java @@ -90,7 +90,7 @@ public class AppStateInstallAppsBridge extends AppStateBaseBridge { return mAppOpsManager.checkOpNoThrow(appOpCode, uid, packageName); } - InstallAppsState createInstallAppsStateFor(String packageName, int uid) { + public InstallAppsState createInstallAppsStateFor(String packageName, int uid) { final InstallAppsState appState = new InstallAppsState(); appState.permissionRequested = hasRequestedAppOpPermission( Manifest.permission.REQUEST_INSTALL_PACKAGES, packageName); diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java index 6f940159298..2098bd6bf48 100755 --- a/src/com/android/settings/applications/InstalledAppDetails.java +++ b/src/com/android/settings/applications/InstalledAppDetails.java @@ -75,6 +75,11 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; +import com.android.settings.applications.appinfo.DrawOverlayDetails; +import com.android.settings.applications.appinfo.ExternalSourcesDetails; +import com.android.settings.applications.appinfo.PictureInPictureDetails; +import com.android.settings.applications.appinfo.PictureInPictureSettings; +import com.android.settings.applications.appinfo.WriteSettingsDetails; import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController; import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController; import com.android.settings.applications.defaultapps.DefaultHomePreferenceController; diff --git a/src/com/android/settings/applications/appinfo/DrawOverlayDetailPreferenceController.java b/src/com/android/settings/applications/appinfo/DrawOverlayDetailPreferenceController.java new file mode 100644 index 00000000000..314d7995bf7 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/DrawOverlayDetailPreferenceController.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.appinfo; + +import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.os.UserManager; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.applications.AppInfoDashboardFragment; + +public class DrawOverlayDetailPreferenceController extends AppInfoPreferenceControllerBase { + + private static final String KEY = "system_alert_window"; + + public DrawOverlayDetailPreferenceController(Context context, AppInfoDashboardFragment parent) { + super(context, parent, KEY); + } + + @Override + public int getAvailabilityStatus() { + if (UserManager.get(mContext).isManagedProfile()) { + return DISABLED_FOR_USER; + } + final PackageInfo packageInfo = mParent.getPackageInfo(); + if (packageInfo == null || packageInfo.requestedPermissions == null) { + return DISABLED_FOR_USER; + } + for (int i = 0; i < packageInfo.requestedPermissions.length; i++) { + if (packageInfo.requestedPermissions[i].equals(SYSTEM_ALERT_WINDOW)) { + return AVAILABLE; + } + } + return DISABLED_FOR_USER; + } + + @Override + public void updateState(Preference preference) { + preference.setSummary(getSummary()); + } + + @Override + protected Class getDetailFragmentClass() { + return DrawOverlayDetails.class; + } + + @VisibleForTesting + CharSequence getSummary() { + return DrawOverlayDetails.getSummary(mContext, mParent.getAppEntry()); + } + +} diff --git a/src/com/android/settings/applications/DrawOverlayDetails.java b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java similarity index 90% rename from src/com/android/settings/applications/DrawOverlayDetails.java rename to src/com/android/settings/applications/appinfo/DrawOverlayDetails.java index 78f1c082042..e8400a0c369 100644 --- a/src/com/android/settings/applications/DrawOverlayDetails.java +++ b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import android.app.AlertDialog; import android.app.AppOpsManager; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings; @@ -29,12 +31,13 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener; import android.support.v7.preference.Preference.OnPreferenceClickListener; import android.util.Log; -import android.view.Window; import android.view.WindowManager; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; +import com.android.settings.applications.AppInfoWithHeader; import com.android.settings.applications.AppStateAppOpsBridge.PermissionState; +import com.android.settings.applications.AppStateOverlayBridge; import com.android.settings.applications.AppStateOverlayBridge.OverlayState; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.applications.ApplicationsState.AppEntry; @@ -44,7 +47,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference"; - private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description"; private static final String LOG_TAG = "DrawOverlayDetails"; private static final int [] APP_OPS_OP_CODE = { @@ -57,7 +59,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc private AppOpsManager mAppOpsManager; private SwitchPreference mSwitchPref; private Preference mOverlayPrefs; - private Preference mOverlayDesc; private Intent mSettingsIntent; private OverlayState mOverlayState; @@ -70,16 +71,9 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); // find preferences - addPreferencesFromResource(R.xml.app_ops_permissions_details); + addPreferencesFromResource(R.xml.draw_overlay_permissions_details); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); mOverlayPrefs = findPreference(KEY_APP_OPS_SETTINGS_PREFS); - mOverlayDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC); - - // set title/summary for all of them - getPreferenceScreen().setTitle(R.string.draw_overlay); - mSwitchPref.setTitle(R.string.permit_draw_overlay); - mOverlayPrefs.setTitle(R.string.app_overlay_permission_preference); - mOverlayDesc.setSummary(R.string.allow_overlay_description); // install event listeners mSwitchPref.setOnPreferenceChangeListener(this); @@ -116,7 +110,8 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc try { getActivity().startActivityAsUser(mSettingsIntent, new UserHandle(mUserId)); } catch (ActivityNotFoundException e) { - Log.w(LOG_TAG, "Unable to launch app draw overlay settings " + mSettingsIntent, e); + Log.w(LOG_TAG, "Unable to launch app draw overlay settings " + mSettingsIntent, + e); } } return true; @@ -161,7 +156,14 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc // you cannot ask a user to grant you a permission you did not have! mSwitchPref.setEnabled(mOverlayState.permissionDeclared && mOverlayState.controlEnabled); mOverlayPrefs.setEnabled(isAllowed); - getPreferenceScreen().removePreference(mOverlayPrefs); + + ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent, + PackageManager.GET_META_DATA, mUserId); + if (resolveInfo == null) { + if (findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) { + getPreferenceScreen().removePreference(mOverlayPrefs); + } + } return true; } diff --git a/src/com/android/settings/applications/appinfo/ExternalSourceDetailPreferenceController.java b/src/com/android/settings/applications/appinfo/ExternalSourceDetailPreferenceController.java new file mode 100644 index 00000000000..4ac67ed77a5 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/ExternalSourceDetailPreferenceController.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.appinfo; + +import android.content.Context; +import android.os.UserManager; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.applications.AppInfoDashboardFragment; +import com.android.settings.applications.AppStateInstallAppsBridge; + +public class ExternalSourceDetailPreferenceController extends AppInfoPreferenceControllerBase { + + private static final String KEY = "install_other_apps"; + + private final String mPackageName; + + public ExternalSourceDetailPreferenceController(Context context, + AppInfoDashboardFragment parent, String packageName) { + super(context, parent, KEY); + mPackageName = packageName; + } + + @Override + public int getAvailabilityStatus() { + if (UserManager.get(mContext).isManagedProfile()) { + return DISABLED_FOR_USER; + } + return isPotentialAppSource() ? AVAILABLE : DISABLED_FOR_USER; + } + + @Override + public void updateState(Preference preference) { + preference.setSummary(getPreferenceSummary()); + } + + @Override + protected Class getDetailFragmentClass() { + return ExternalSourcesDetails.class; + } + + @VisibleForTesting + CharSequence getPreferenceSummary() { + return ExternalSourcesDetails.getPreferenceSummary(mContext, mParent.getAppEntry()); + } + + @VisibleForTesting + boolean isPotentialAppSource() { + AppStateInstallAppsBridge.InstallAppsState appState = + new AppStateInstallAppsBridge(mContext, null, null).createInstallAppsStateFor( + mPackageName, mParent.getPackageInfo().applicationInfo.uid); + return appState.isPotentialAppSource(); + } + +} diff --git a/src/com/android/settings/applications/ExternalSourcesDetails.java b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java similarity index 96% rename from src/com/android/settings/applications/ExternalSourcesDetails.java rename to src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java index 5cd3c44ae76..04000666d0c 100644 --- a/src/com/android/settings/applications/ExternalSourcesDetails.java +++ b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; @@ -30,6 +30,8 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.Settings; +import com.android.settings.applications.AppInfoWithHeader; +import com.android.settings.applications.AppStateInstallAppsBridge; import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState; import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.applications.ApplicationsState.AppEntry; diff --git a/src/com/android/settings/applications/appinfo/PictureInPictureDetailPreferenceController.java b/src/com/android/settings/applications/appinfo/PictureInPictureDetailPreferenceController.java new file mode 100644 index 00000000000..aea6baef922 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/PictureInPictureDetailPreferenceController.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.appinfo; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.UserHandle; +import android.os.UserManager; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; +import android.util.Log; + +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.applications.AppInfoDashboardFragment; + +public class PictureInPictureDetailPreferenceController extends AppInfoPreferenceControllerBase { + + private static final String KEY = "picture_in_picture"; + private static final String TAG = "PicInPicDetailControl"; + + private final PackageManager mPackageManager; + private final String mPackageName; + + public PictureInPictureDetailPreferenceController(Context context, + AppInfoDashboardFragment parent, String packageName) { + super(context, parent, KEY); + mPackageManager = context.getPackageManager(); + mPackageName = packageName; + } + + @Override + public int getAvailabilityStatus() { + if (UserManager.get(mContext).isManagedProfile()) { + return DISABLED_FOR_USER; + } + return hasPictureInPictureActivites() ? AVAILABLE : DISABLED_FOR_USER; + } + + @Override + public void updateState(Preference preference) { + preference.setSummary(getPreferenceSummary()); + } + + @Override + protected Class getDetailFragmentClass() { + return PictureInPictureDetails.class; + } + + @VisibleForTesting + boolean hasPictureInPictureActivites() { + // Get the package info with the activities + PackageInfo packageInfoWithActivities = null; + try { + packageInfoWithActivities = mPackageManager.getPackageInfoAsUser(mPackageName, + PackageManager.GET_ACTIVITIES, UserHandle.myUserId()); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Exception while retrieving the package info of " + mPackageName, e); + } + + return packageInfoWithActivities != null + && PictureInPictureSettings.checkPackageHasPictureInPictureActivities( + packageInfoWithActivities.packageName, + packageInfoWithActivities.activities); + } + + @VisibleForTesting + int getPreferenceSummary() { + return PictureInPictureDetails.getPreferenceSummary(mContext, + mParent.getPackageInfo().applicationInfo.uid, mPackageName); + } +} diff --git a/src/com/android/settings/applications/PictureInPictureDetails.java b/src/com/android/settings/applications/appinfo/PictureInPictureDetails.java similarity index 81% rename from src/com/android/settings/applications/PictureInPictureDetails.java rename to src/com/android/settings/applications/appinfo/PictureInPictureDetails.java index a886a3df554..1d9a5440d64 100644 --- a/src/com/android/settings/applications/PictureInPictureDetails.java +++ b/src/com/android/settings/applications/appinfo/PictureInPictureDetails.java @@ -13,14 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import android.app.AlertDialog; import android.app.AppOpsManager; import android.content.Context; -import android.content.Intent; import android.os.Bundle; -import android.provider.Settings; import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.Preference; import android.support.v7.preference.Preference.OnPreferenceChangeListener; @@ -28,6 +26,7 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; +import com.android.settings.applications.AppInfoWithHeader; import com.android.settings.overlay.FeatureFactory; import static android.app.AppOpsManager.MODE_ALLOWED; @@ -38,42 +37,31 @@ public class PictureInPictureDetails extends AppInfoWithHeader implements OnPreferenceChangeListener { private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; - private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference"; - private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description"; private static final String LOG_TAG = "PictureInPictureDetails"; private SwitchPreference mSwitchPref; - private Preference mOverlayDesc; - private Intent mSettingsIntent; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // find preferences - addPreferencesFromResource(R.xml.app_ops_permissions_details); + addPreferencesFromResource(R.xml.picture_in_picture_permissions_details); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); - mOverlayDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC); - getPreferenceScreen().removePreference(findPreference(KEY_APP_OPS_SETTINGS_PREFS)); // set title/summary for all of them - getPreferenceScreen().setTitle(R.string.picture_in_picture_app_detail_title); mSwitchPref.setTitle(R.string.picture_in_picture_app_detail_switch); - mOverlayDesc.setSummary(R.string.picture_in_picture_app_detail_summary); // install event listeners mSwitchPref.setOnPreferenceChangeListener(this); - - mSettingsIntent = new Intent(Intent.ACTION_MAIN) - .setAction(Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS); } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference == mSwitchPref) { logSpecialPermissionChange((Boolean) newValue, mPackageName); - setEnterPipStateForPackage(getActivity(), mPackageInfo.applicationInfo.uid, mPackageName, - (Boolean) newValue); + setEnterPipStateForPackage(getActivity(), mPackageInfo.applicationInfo.uid, + mPackageName, (Boolean) newValue); return true; } return false; @@ -121,7 +109,7 @@ public class PictureInPictureDetails extends AppInfoWithHeader * @return the summary for the current state of whether the app associated with the given * {@param packageName} is allowed to enter picture-in-picture. */ - static int getPreferenceSummary(Context context, int uid, String packageName) { + public static int getPreferenceSummary(Context context, int uid, String packageName) { final boolean enabled = PictureInPictureDetails.getEnterPipStateForPackage(context, uid, packageName); return enabled ? R.string.app_permission_summary_allowed diff --git a/src/com/android/settings/applications/PictureInPictureSettings.java b/src/com/android/settings/applications/appinfo/PictureInPictureSettings.java similarity index 97% rename from src/com/android/settings/applications/PictureInPictureSettings.java rename to src/com/android/settings/applications/appinfo/PictureInPictureSettings.java index 01d14f49c6c..28cdf689b0e 100644 --- a/src/com/android/settings/applications/PictureInPictureSettings.java +++ b/src/com/android/settings/applications/appinfo/PictureInPictureSettings.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import static android.content.pm.PackageManager.GET_ACTIVITIES; @@ -37,6 +37,7 @@ import android.view.View; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; +import com.android.settings.applications.AppInfoBase; import com.android.settings.notification.EmptyTextSettings; import com.android.settings.widget.AppPreference; import com.android.settings.wrapper.ActivityInfoWrapper; @@ -95,7 +96,7 @@ public class PictureInPictureSettings extends EmptyTextSettings { * @return true if the package has any activities that declare that they support * picture-in-picture. */ - static boolean checkPackageHasPictureInPictureActivities(String packageName, + public static boolean checkPackageHasPictureInPictureActivities(String packageName, ActivityInfo[] activities) { ActivityInfoWrapper[] wrappedActivities = null; if (activities != null) { diff --git a/src/com/android/settings/applications/WriteSettingsDetails.java b/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java similarity index 90% rename from src/com/android/settings/applications/WriteSettingsDetails.java rename to src/com/android/settings/applications/appinfo/WriteSettingsDetails.java index 50e6948bbf1..a65de32efc2 100644 --- a/src/com/android/settings/applications/WriteSettingsDetails.java +++ b/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import android.app.AlertDialog; import android.app.AppOpsManager; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings; @@ -31,7 +33,9 @@ import android.util.Log; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; +import com.android.settings.applications.AppInfoWithHeader; import com.android.settings.applications.AppStateAppOpsBridge.PermissionState; +import com.android.settings.applications.AppStateWriteSettingsBridge; import com.android.settings.applications.AppStateWriteSettingsBridge.WriteSettingsState; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.applications.ApplicationsState.AppEntry; @@ -42,7 +46,6 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere private static final String KEY_APP_OPS_PREFERENCE_SCREEN = "app_ops_preference_screen"; private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference"; - private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description"; private static final String LOG_TAG = "WriteSettingsDetails"; private static final int [] APP_OPS_OP_CODE = { @@ -55,7 +58,6 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere private AppOpsManager mAppOpsManager; private SwitchPreference mSwitchPref; private Preference mWriteSettingsPrefs; - private Preference mWriteSettingsDesc; private Intent mSettingsIntent; private WriteSettingsState mWriteSettingsState; @@ -67,15 +69,9 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere mAppBridge = new AppStateWriteSettingsBridge(context, mState, null); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); - addPreferencesFromResource(R.xml.app_ops_permissions_details); + addPreferencesFromResource(R.xml.write_system_settings_permissions_details); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); mWriteSettingsPrefs = findPreference(KEY_APP_OPS_SETTINGS_PREFS); - mWriteSettingsDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC); - - getPreferenceScreen().setTitle(R.string.write_settings); - mSwitchPref.setTitle(R.string.permit_write_settings); - mWriteSettingsPrefs.setTitle(R.string.write_settings_preference); - mWriteSettingsDesc.setSummary(R.string.write_settings_description); mSwitchPref.setOnPreferenceChangeListener(this); mWriteSettingsPrefs.setOnPreferenceClickListener(this); @@ -147,8 +143,13 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere // you can't ask a user for a permission you didn't even declare! mSwitchPref.setEnabled(mWriteSettingsState.permissionDeclared); mWriteSettingsPrefs.setEnabled(canWrite); - if (getPreferenceScreen().findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) { - getPreferenceScreen().removePreference(mWriteSettingsPrefs); + + ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent, + PackageManager.GET_META_DATA, mUserId); + if (resolveInfo == null) { + if (getPreferenceScreen().findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) { + getPreferenceScreen().removePreference(mWriteSettingsPrefs); + } } return true; } diff --git a/src/com/android/settings/applications/appinfo/WriteSystemSettingsPreferenceController.java b/src/com/android/settings/applications/appinfo/WriteSystemSettingsPreferenceController.java new file mode 100644 index 00000000000..55b181ab7b4 --- /dev/null +++ b/src/com/android/settings/applications/appinfo/WriteSystemSettingsPreferenceController.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.appinfo; + +import static android.Manifest.permission.WRITE_SETTINGS; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.os.UserManager; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.applications.AppInfoDashboardFragment; + +public class WriteSystemSettingsPreferenceController extends AppInfoPreferenceControllerBase { + + private static final String KEY = "write_settings_apps"; + + public WriteSystemSettingsPreferenceController(Context context, + AppInfoDashboardFragment parent) { + super(context, parent, KEY); + } + + @Override + public int getAvailabilityStatus() { + if (UserManager.get(mContext).isManagedProfile()) { + return DISABLED_FOR_USER; + } + final PackageInfo packageInfo = mParent.getPackageInfo(); + if (packageInfo == null || packageInfo.requestedPermissions == null) { + return DISABLED_FOR_USER; + } + for (int i = 0; i < packageInfo.requestedPermissions.length; i++) { + if (packageInfo.requestedPermissions[i].equals(WRITE_SETTINGS)) { + return AVAILABLE; + } + } + return DISABLED_FOR_USER; + } + + @Override + public void updateState(Preference preference) { + preference.setSummary(getSummary()); + } + + @Override + protected Class getDetailFragmentClass() { + return WriteSettingsDetails.class; + } + + @VisibleForTesting + CharSequence getSummary() { + return WriteSettingsDetails.getSummary(mContext, mParent.getAppEntry()); + } + +} diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index e9d105d2cc0..067e167a92f 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -89,14 +89,14 @@ import com.android.settings.applications.AppStateUsageBridge.UsageState; import com.android.settings.applications.AppStateWriteSettingsBridge; import com.android.settings.applications.AppStorageSettings; import com.android.settings.applications.DefaultAppSettings; -import com.android.settings.applications.DrawOverlayDetails; -import com.android.settings.applications.ExternalSourcesDetails; import com.android.settings.applications.InstalledAppCounter; import com.android.settings.applications.InstalledAppDetails; import com.android.settings.applications.NotificationApps; import com.android.settings.applications.UsageAccessDetails; -import com.android.settings.applications.WriteSettingsDetails; import com.android.settings.applications.AppInfoDashboardFragment; +import com.android.settings.applications.appinfo.DrawOverlayDetails; +import com.android.settings.applications.appinfo.ExternalSourcesDetails; +import com.android.settings.applications.appinfo.WriteSettingsDetails; import com.android.settings.core.FeatureFlags; import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.dashboard.SummaryLoader; diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index 7720b48b84b..ecef57e70c3 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -40,19 +40,19 @@ import com.android.settings.accounts.ManagedProfileSettings; import com.android.settings.accounts.UserAndAccountDashboardFragment; import com.android.settings.applications.AppAndNotificationDashboardFragment; import com.android.settings.applications.DefaultAppSettings; -import com.android.settings.applications.DrawOverlayDetails; -import com.android.settings.applications.ExternalSourcesDetails; import com.android.settings.applications.InstalledAppDetails; import com.android.settings.applications.ManageDomainUrls; import com.android.settings.applications.NotificationApps; -import com.android.settings.applications.PictureInPictureDetails; -import com.android.settings.applications.PictureInPictureSettings; import com.android.settings.applications.ProcessStatsSummary; import com.android.settings.applications.ProcessStatsUi; import com.android.settings.applications.UsageAccessDetails; import com.android.settings.applications.VrListenerSettings; -import com.android.settings.applications.WriteSettingsDetails; import com.android.settings.applications.AppInfoDashboardFragment; +import com.android.settings.applications.appinfo.DrawOverlayDetails; +import com.android.settings.applications.appinfo.ExternalSourcesDetails; +import com.android.settings.applications.appinfo.PictureInPictureDetails; +import com.android.settings.applications.appinfo.PictureInPictureSettings; +import com.android.settings.applications.appinfo.WriteSettingsDetails; import com.android.settings.applications.assist.ManageAssist; import com.android.settings.applications.manageapplications.ManageApplications; import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment; diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable index 245d321f26f..eee2add4b6b 100644 --- a/tests/robotests/assets/grandfather_not_implementing_indexable +++ b/tests/robotests/assets/grandfather_not_implementing_indexable @@ -20,7 +20,7 @@ com.android.settings.datausage.AppDataUsage com.android.settings.datausage.DataPlanUsageSummary com.android.settings.accessibility.FontSizePreferenceFragmentForSetupWizard com.android.settings.applications.ManageDomainUrls -com.android.settings.applications.WriteSettingsDetails +com.android.settings.applications.appinfo.WriteSettingsDetails com.android.settings.applications.ProcessStatsSummary com.android.settings.users.RestrictedProfileSettings com.android.settings.accounts.ChooseAccountActivity @@ -36,7 +36,7 @@ com.android.settings.accessibility.ToggleSelectToSpeakPreferenceFragmentForSetup com.android.settings.accounts.AccountSyncSettings com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment com.android.settings.inputmethod.InputMethodAndSubtypeEnabler -com.android.settings.applications.DrawOverlayDetails +com.android.settings.applications.appinfo.DrawOverlayDetails com.android.settings.backup.ToggleBackupSettingFragment com.android.settings.users.UserDetailsSettings com.android.settings.datausage.UnrestrictedDataAccess @@ -59,9 +59,9 @@ com.android.settings.applications.AppStorageSettings com.android.settings.notification.NotificationAccessSettings com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment com.android.settings.localepicker.LocaleListEditor -com.android.settings.applications.ExternalSourcesDetails -com.android.settings.applications.PictureInPictureSettings -com.android.settings.applications.PictureInPictureDetails +com.android.settings.applications.appinfo.ExternalSourcesDetails +com.android.settings.applications.appinfo.PictureInPictureSettings +com.android.settings.applications.appinfo.PictureInPictureDetails com.android.settings.ApnSettings com.android.settings.PrivacySettings com.android.settings.WifiCallingSettings diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/DrawOverlayDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DrawOverlayDetailPreferenceControllerTest.java new file mode 100644 index 00000000000..a7468b5a69d --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/appinfo/DrawOverlayDetailPreferenceControllerTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.appinfo; + +import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; +import static android.Manifest.permission.WRITE_SETTINGS; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.os.UserManager; +import android.support.v7.preference.Preference; + +import com.android.settings.TestConfig; +import com.android.settings.applications.AppInfoDashboardFragment; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class DrawOverlayDetailPreferenceControllerTest { + + @Mock + private UserManager mUserManager; + @Mock + private AppInfoDashboardFragment mFragment; + @Mock + private Preference mPreference; + + private Context mContext; + private DrawOverlayDetailPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + mController = spy(new DrawOverlayDetailPreferenceController(mContext, mFragment)); + final String key = mController.getPreferenceKey(); + when(mPreference.getKey()).thenReturn(key); + } + + @Test + public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_noPermissionRequested_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(false); + when(mFragment.getPackageInfo()).thenReturn(new PackageInfo()); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_noSystemAlertWindowPermission_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(false); + final PackageInfo info = new PackageInfo(); + info.requestedPermissions = new String[] {WRITE_SETTINGS}; + when(mFragment.getPackageInfo()).thenReturn(info); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_hasSystemAlertWindowPermission_shouldReturnAvailable() { + when(mUserManager.isManagedProfile()).thenReturn(false); + final PackageInfo info = new PackageInfo(); + info.requestedPermissions = new String[] {SYSTEM_ALERT_WINDOW}; + when(mFragment.getPackageInfo()).thenReturn(info); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE); + } + + @Test + public void getDetailFragmentClass_shouldReturnDrawOverlayDetails() { + assertThat(mController.getDetailFragmentClass()).isEqualTo(DrawOverlayDetails.class); + } + + @Test + public void updateState_shouldSetSummary() { + final String summary = "test summary"; + doReturn(summary).when(mController).getSummary(); + + mController.updateState(mPreference); + + verify(mPreference).setSummary(summary); + } + +} diff --git a/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/DrawOverlayDetailsTest.java similarity index 98% rename from tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java rename to tests/robotests/src/com/android/settings/applications/appinfo/DrawOverlayDetailsTest.java index 94dc1377cc4..a33a6b8fabc 100644 --- a/tests/robotests/src/com/android/settings/applications/DrawOverlayDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/DrawOverlayDetailsTest.java @@ -14,7 +14,7 @@ * limitations under the License */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.nullable; diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourceDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourceDetailPreferenceControllerTest.java new file mode 100644 index 00000000000..d500be901b2 --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourceDetailPreferenceControllerTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.appinfo; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.UserManager; +import android.support.v7.preference.Preference; + +import com.android.settings.TestConfig; +import com.android.settings.applications.AppInfoDashboardFragment; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class ExternalSourceDetailPreferenceControllerTest { + + @Mock + private UserManager mUserManager; + @Mock + private AppInfoDashboardFragment mFragment; + @Mock + private Preference mPreference; + + private Context mContext; + private ExternalSourceDetailPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + mController = spy( + new ExternalSourceDetailPreferenceController(mContext, mFragment, "Package1")); + final String key = mController.getPreferenceKey(); + when(mPreference.getKey()).thenReturn(key); + } + + @Test + public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_notPotentialAppSource_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(false); + doReturn(false).when(mController).isPotentialAppSource(); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_isPotentialAppSource_shouldReturnAvailable() { + when(mUserManager.isManagedProfile()).thenReturn(false); + doReturn(true).when(mController).isPotentialAppSource(); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE); + } + + @Test + public void getDetailFragmentClass_shouldReturnExternalSourcesDetails() { + assertThat(mController.getDetailFragmentClass()).isEqualTo(ExternalSourcesDetails.class); + } + + @Test + public void updateState_shouldSetSummary() { + final String summary = "test summary"; + doReturn(summary).when(mController).getPreferenceSummary(); + + mController.updateState(mPreference); + + verify(mPreference).setSummary(summary); + } + +} diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureDetailPreferenceControllerTest.java new file mode 100644 index 00000000000..7d8116899ca --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureDetailPreferenceControllerTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.appinfo; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.UserManager; +import android.support.v7.preference.Preference; + +import com.android.settings.R; +import com.android.settings.TestConfig; +import com.android.settings.applications.AppInfoDashboardFragment; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class PictureInPictureDetailPreferenceControllerTest { + + @Mock + private UserManager mUserManager; + @Mock + private AppInfoDashboardFragment mFragment; + @Mock + private Preference mPreference; + + private Context mContext; + private PictureInPictureDetailPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + + mController = spy( + new PictureInPictureDetailPreferenceController(mContext, mFragment, "Package1")); + final String key = mController.getPreferenceKey(); + when(mPreference.getKey()).thenReturn(key); + } + + @Test + public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_noPictureInPictureActivities_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(false); + doReturn(false).when(mController).hasPictureInPictureActivites(); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_hasPictureInPictureActivities_shouldReturnAvailable() { + when(mUserManager.isManagedProfile()).thenReturn(false); + doReturn(true).when(mController).hasPictureInPictureActivites(); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE); + } + + @Test + public void getDetailFragmentClass_shouldReturnPictureInPictureDetails() { + assertThat(mController.getDetailFragmentClass()).isEqualTo(PictureInPictureDetails.class); + } + + @Test + public void updateState_shouldSetSummary() { + final int summary = R.string.app_permission_summary_allowed; + doReturn(summary).when(mController).getPreferenceSummary(); + + mController.updateState(mPreference); + + verify(mPreference).setSummary(summary); + } + +} diff --git a/tests/robotests/src/com/android/settings/applications/PictureInPictureDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureDetailsTest.java similarity index 98% rename from tests/robotests/src/com/android/settings/applications/PictureInPictureDetailsTest.java rename to tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureDetailsTest.java index 03691307a20..da603ca222e 100644 --- a/tests/robotests/src/com/android/settings/applications/PictureInPictureDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureDetailsTest.java @@ -14,7 +14,7 @@ * limitations under the License */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.nullable; diff --git a/tests/robotests/src/com/android/settings/applications/PictureInPictureSettingsTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureSettingsTest.java similarity index 99% rename from tests/robotests/src/com/android/settings/applications/PictureInPictureSettingsTest.java rename to tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureSettingsTest.java index dd3ec85e890..2ec9c9694af 100644 --- a/tests/robotests/src/com/android/settings/applications/PictureInPictureSettingsTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/PictureInPictureSettingsTest.java @@ -14,7 +14,7 @@ * limitations under the License */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import static com.google.common.truth.Truth.assertThat; diff --git a/tests/robotests/src/com/android/settings/applications/WriteSettingsDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/WriteSettingsDetailsTest.java similarity index 97% rename from tests/robotests/src/com/android/settings/applications/WriteSettingsDetailsTest.java rename to tests/robotests/src/com/android/settings/applications/appinfo/WriteSettingsDetailsTest.java index c2abefafb46..edcf64b7932 100644 --- a/tests/robotests/src/com/android/settings/applications/WriteSettingsDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/WriteSettingsDetailsTest.java @@ -14,7 +14,7 @@ * limitations under the License */ -package com.android.settings.applications; +package com.android.settings.applications.appinfo; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.eq; diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/WriteSystemSettingsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/WriteSystemSettingsPreferenceControllerTest.java new file mode 100644 index 00000000000..fabcbb20439 --- /dev/null +++ b/tests/robotests/src/com/android/settings/applications/appinfo/WriteSystemSettingsPreferenceControllerTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications.appinfo; + +import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; +import static android.Manifest.permission.WRITE_SETTINGS; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.os.UserManager; +import android.support.v7.preference.Preference; + +import com.android.settings.TestConfig; +import com.android.settings.applications.AppInfoDashboardFragment; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class WriteSystemSettingsPreferenceControllerTest { + + @Mock + private UserManager mUserManager; + @Mock + private AppInfoDashboardFragment mFragment; + @Mock + private Preference mPreference; + + private Context mContext; + private WriteSystemSettingsPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + mController = spy(new WriteSystemSettingsPreferenceController(mContext, mFragment)); + final String key = mController.getPreferenceKey(); + when(mPreference.getKey()).thenReturn(key); + } + + @Test + public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(true); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_noPermissionRequested_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(false); + when(mFragment.getPackageInfo()).thenReturn(new PackageInfo()); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_noWriteSettingsPermission_shouldReturnDisabled() { + when(mUserManager.isManagedProfile()).thenReturn(false); + final PackageInfo info = new PackageInfo(); + info.requestedPermissions = new String[] {SYSTEM_ALERT_WINDOW}; + when(mFragment.getPackageInfo()).thenReturn(info); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER); + } + + @Test + public void getAvailabilityStatus_hasWriteSettingsPermission_shouldReturnAvailable() { + when(mUserManager.isManagedProfile()).thenReturn(false); + final PackageInfo info = new PackageInfo(); + info.requestedPermissions = new String[] {WRITE_SETTINGS}; + when(mFragment.getPackageInfo()).thenReturn(info); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE); + } + + @Test + public void getDetailFragmentClass_shouldReturnWriteSettingsDetails() { + assertThat(mController.getDetailFragmentClass()).isEqualTo(WriteSettingsDetails.class); + } + + @Test + public void updateState_shouldSetSummary() { + final String summary = "test summary"; + doReturn(summary).when(mController).getSummary(); + + mController.updateState(mPreference); + + verify(mPreference).setSummary(summary); + } + +} From 3ba03815670d6d8ac7bd20e2e0c7c10fd34a5392 Mon Sep 17 00:00:00 2001 From: Fan Zhang Date: Thu, 7 Dec 2017 12:48:12 -0800 Subject: [PATCH 08/13] Update feature flag dashboard UI to display all features Bug: 36222960 Test: robotests Change-Id: I1aea8f32df9bd8ae24708374b60d173953a7c266 --- src/com/android/settings/DeviceInfoSettings.java | 8 ++++---- .../suggestions/SuggestionFeatureProviderImpl.java | 2 +- .../FeatureFlagsPreferenceController.java | 11 ++--------- .../deviceinfo/DeviceModelPreferenceController.java | 2 +- .../deviceinfo/HardwareInfoDialogFragment.java | 2 +- .../com/android/settings/DeviceInfoSettingsTest.java | 5 +++++ .../FeatureFlagPreferenceControllerTest.java | 3 ++- .../DeviceModelPreferenceControllerTest.java | 9 +++++++++ 8 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/com/android/settings/DeviceInfoSettings.java b/src/com/android/settings/DeviceInfoSettings.java index f99b894e83f..74ce5d054c9 100644 --- a/src/com/android/settings/DeviceInfoSettings.java +++ b/src/com/android/settings/DeviceInfoSettings.java @@ -84,7 +84,7 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable { public void onCreate(Bundle icicle) { super.onCreate(icicle); final Bundle arguments = getArguments(); - if (FeatureFlagUtils.isEnabled(getContext(), DEVICE_INFO_V2) || true) { + if (FeatureFlagUtils.isEnabled(getContext(), DEVICE_INFO_V2)) { // Do not override initial expand children count if we come from // search (EXTRA_FRAGMENT_ARG_KEY is set) - we need to display every if entry point // is search. @@ -119,7 +119,7 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable { @Override protected int getPreferenceScreenResId() { - return FeatureFlagUtils.isEnabled(getContext(), DEVICE_INFO_V2) || true + return FeatureFlagUtils.isEnabled(getContext(), DEVICE_INFO_V2) ? R.xml.device_info_settings_v2 : R.xml.device_info_settings; } @@ -156,7 +156,7 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable { private static List buildPreferenceControllers(Context context, Activity activity, Fragment fragment, Lifecycle lifecycle) { - if (FeatureFlagUtils.isEnabled(context, DEVICE_INFO_V2) || true) { + if (FeatureFlagUtils.isEnabled(context, DEVICE_INFO_V2)) { final List controllers = new ArrayList<>(); // Device name @@ -220,7 +220,7 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable { public List getXmlResourcesToIndex( Context context, boolean enabled) { final SearchIndexableResource sir = new SearchIndexableResource(context); - sir.xmlResId = FeatureFlagUtils.isEnabled(context, DEVICE_INFO_V2) || true + sir.xmlResId = FeatureFlagUtils.isEnabled(context, DEVICE_INFO_V2) ? R.xml.device_info_settings_v2 : R.xml.device_info_settings; return Arrays.asList(sir); } diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java index 4f4753ab37e..3fc2fb2953f 100644 --- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java +++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java @@ -92,7 +92,7 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider } private static boolean isV2Enabled(Context context) { - return FeatureFlagUtils.isEnabled(context, SUGGESTIONS_V2) || true; + return FeatureFlagUtils.isEnabled(context, SUGGESTIONS_V2); } @Override diff --git a/src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java b/src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java index 7c00591c02f..fe565eda491 100644 --- a/src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java +++ b/src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java @@ -17,7 +17,6 @@ package com.android.settings.development.featureflags; import android.content.Context; -import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.util.FeatureFlagUtils; @@ -68,14 +67,8 @@ public class FeatureFlagsPreferenceController extends AbstractPreferenceControll } mScreen.removeAll(); final Context prefContext = mScreen.getContext(); - for (String prefixedFeature : featureMap.keySet()) { - if (prefixedFeature.startsWith(FeatureFlagUtils.FFLAG_PREFIX) - && !prefixedFeature.startsWith(FeatureFlagUtils.FFLAG_OVERRIDE_PREFIX)) { - final String feature = prefixedFeature.substring( - FeatureFlagUtils.FFLAG_PREFIX.length()); - final Preference pref = new FeatureFlagPreference(prefContext, feature); - mScreen.addPreference(pref); - } + for (String feature : featureMap.keySet()) { + mScreen.addPreference(new FeatureFlagPreference(prefContext, feature)); } } } diff --git a/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java b/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java index 89df7cc3bec..7934ad7ced2 100644 --- a/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java +++ b/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java @@ -51,7 +51,7 @@ public class DeviceModelPreferenceController extends AbstractPreferenceControlle super.displayPreference(screen); final Preference pref = screen.findPreference(KEY_DEVICE_MODEL); if (pref != null) { - if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DEVICE_INFO_V2) || true) { + if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.DEVICE_INFO_V2)) { pref.setSummary(mContext.getResources().getString(R.string.model_summary, getDeviceModel())); } else { diff --git a/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java b/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java index d1c6447d3a7..26f1ac2b53e 100644 --- a/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java +++ b/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java @@ -59,7 +59,7 @@ public class HardwareInfoDialogFragment extends InstrumentedDialogFragment { DeviceModelPreferenceController.getDeviceModel()); // Serial number - if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DEVICE_INFO_V2) || true) { + if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DEVICE_INFO_V2)) { setText(content, R.id.serial_number_label, R.id.serial_number_value, getSerialNumber()); } else { content.findViewById(R.id.serial_number_label).setVisibility(View.GONE); diff --git a/tests/robotests/src/com/android/settings/DeviceInfoSettingsTest.java b/tests/robotests/src/com/android/settings/DeviceInfoSettingsTest.java index 78f5bdf632b..486993d1b7b 100644 --- a/tests/robotests/src/com/android/settings/DeviceInfoSettingsTest.java +++ b/tests/robotests/src/com/android/settings/DeviceInfoSettingsTest.java @@ -94,7 +94,12 @@ public class DeviceInfoSettingsTest { } @Test + @Config(shadows = { + SettingsShadowSystemProperties.class + }) public void getPrefXml_shouldReturnDeviceInfoXml() { + SystemProperties.set(FeatureFlagUtils.FFLAG_OVERRIDE_PREFIX + FeatureFlags.DEVICE_INFO_V2, + "true"); assertThat(mSettings.getPreferenceScreenResId()).isEqualTo(R.xml.device_info_settings_v2); } diff --git a/tests/robotests/src/com/android/settings/development/featureflags/FeatureFlagPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/featureflags/FeatureFlagPreferenceControllerTest.java index e505d033aae..f831506a8d1 100644 --- a/tests/robotests/src/com/android/settings/development/featureflags/FeatureFlagPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/featureflags/FeatureFlagPreferenceControllerTest.java @@ -21,6 +21,7 @@ import static android.arch.lifecycle.Lifecycle.Event.ON_START; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -70,6 +71,6 @@ public class FeatureFlagPreferenceControllerTest { mLifecycle.handleLifecycleEvent(ON_START); verify(mScreen).removeAll(); - verify(mScreen).addPreference(any(FeatureFlagPreference.class)); + verify(mScreen, atLeastOnce()).addPreference(any(FeatureFlagPreference.class)); } } diff --git a/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java index 1c8bde1dba6..347ca3ac308 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java @@ -26,12 +26,16 @@ import static org.mockito.Mockito.when; import android.app.Fragment; import android.content.Context; +import android.os.SystemProperties; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; +import android.util.FeatureFlagUtils; import com.android.settings.R; import com.android.settings.TestConfig; +import com.android.settings.core.FeatureFlags; import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.shadow.SettingsShadowSystemProperties; import org.junit.Before; import org.junit.Test; @@ -72,7 +76,12 @@ public class DeviceModelPreferenceControllerTest { } @Test + @Config(shadows = { + SettingsShadowSystemProperties.class + }) public void displayPref_shouldSetSummary() { + SystemProperties.set(FeatureFlagUtils.FFLAG_OVERRIDE_PREFIX + FeatureFlags.DEVICE_INFO_V2, + "true"); mController.displayPreference(mPreferenceScreen); verify(mPreference).setSummary(mContext.getResources().getString(R.string.model_summary, From 3ea52be26d44569689cd09607d4f63cf77814238 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 7 Dec 2017 17:08:11 -0800 Subject: [PATCH 09/13] Import translations. DO NOT MERGE Auto-generated-cl: translation import Bug: 64712476 Change-Id: I59dde21252b7681bb6dfcf9dae1f27192a3cd19e --- res/values-bs/strings.xml | 35 +++++------ res/values-ca/strings.xml | 13 ++-- res/values-de/strings.xml | 9 ++- res/values-fa/strings.xml | 11 ++-- res/values-mr/strings.xml | 13 ++-- res/values-pt-rPT/strings.xml | 115 +++++++++++++++++----------------- res/values-uk/strings.xml | 7 +-- 7 files changed, 98 insertions(+), 105 deletions(-) diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 36eb82a4825..a94d2d17971 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -54,7 +54,7 @@ "Nije registrirano" "Dostupno" "Nedostupno" - "IMS registracija: %1$s\nGovor putem LTE mreže: %2$s\nGovor putem Wi-Fi mreže: %3$s\nVideo pozivanje: %4$s\nUT sučelje: %5$s" + "IMS registracija: %1$s\nGovor putem LTE mreže: %2$s\nGovor putem Wi-Fi mreže: %3$s\nVideo pozivanje: %4$s\nUT interfejs: %5$s" "Aktivan" "Ne radi" "Samo pozivi za hitne slučajeve" @@ -114,7 +114,7 @@ "Vaš tablet će prekinuti vezu s uređajem %1$s." "Vaš uređaj će prekinuti vezu s uređajem %1$s." "Prekini vezu" - "Nemate dozvolu da mijenjate postavke za Bluetooth." + "Nemate odobrenje da mijenjate postavke za Bluetooth." "Uparivanje novog uređaja" "Uređaj %1$s je vidljiv uređajima u blizini, dok su postavke Bluetootha otvorene." "Bluetooth adresa telefona: %1$s" @@ -635,7 +635,8 @@ "Da biste izvršilu uparivanje s uređajem:<br><b>%1$s</b><br><br>Provjerite da li se prikazuje sljedeći pristupni ključ:<br><b>%2$s</b>" "Od:<br><b>%1$s</b><br><br>Želite izvršiti uparivanje s ovim uređajem?" "Da biste izvršili uparivanje s uređajem:<br><b>%1$s</b><br><br>Otkucajte na njemu:<br><b>%2$s</b>, a zatim pritisnite Return ili Enter." - "Dozvoli uređaju %1$s pristup mojim kontaktima i istoriji poziva" + + "Nije uspjelo povezivanje sa uređajem %1$s." "Potraži uređaje" @@ -778,7 +779,7 @@ "Piši na NFC oznake" "Da biste vidjeli dostupne mreže, uključite Wi-Fi." "Traži se Wi-Fi mreža..." - "Nemate dozvolu za promjenu Wi-Fi mreže." + "Nemate odobrenje za promjenu Wi-Fi mreže." "Još" "Autom. postavljanje (WPS)" "Napredne opcije" @@ -819,7 +820,7 @@ "Opseg od 2.4 GHz" "Opseg od 5 GHz" "IP postavke" - "Podijeli s ostalim korisnicima uređaja" + "Dijeli s ostalim korisnicima uređaja" "(nepromijenjeno)" "Odaberite" "(dodano je više certifikata)" @@ -1404,7 +1405,7 @@ "Dijeljenje internetske veze tableta putem Bluetootha" "Dijeljenje internetske veze telefona putem Bluetootha" "Dijeljenje internetske veze uređaja %1$d putem Bluetootha" - "Ne može se povezati sa više od %1$d uređaja." + "Nije se moguće povezati sa više od %1$d uređaja." "Prestat će se dijeliti veza s uređajem %1$s." "Koristite pristupnu tačku i dijeljenje veze za pružanje interneta drugim uređajima putem mobilnog prijenosa podataka. Aplikacije također mogu kreirati pristupne tačke za dijeljenje sadržaja s uređajima u blizini." "Pomoć" @@ -1457,7 +1458,7 @@ "Lokacija i Google pretraživanje" "Dopustite da Google koristi vašu lokaciju radi poboljšavanja rezultata pretraživanja i drugih usluga" "Pristup mojoj lokaciji" - "Dopustite aplikacijama koje su zatražile vašu dozvolu da koriste informacije o vašoj lokaciji" + "Dopustite aplikacijama koje su zatražile vaše odobrenje da koriste informacije o vašoj lokaciji" "Izvori lokacije" "O tabletu" "O telefonu" @@ -1576,7 +1577,7 @@ "Zadano otvori" "Zadane vrijednosti" "Kompatibilnost ekrana" - "Dozvole" + "Odobrenja" "Keš" "Obriši keš memoriju" "Keš" @@ -1602,7 +1603,7 @@ "Obriši podatke" "Deinstaliraj ažuriranja" "Odabrali ste zadano pokretanje ove aplikacije za neke radnje." - "Odabrali ste da ovoj aplikaciji dodijelite dozvolu za kreiranje vidžeta i pristup njihovim podacima." + "Odabrali ste da ovoj aplikaciji dodijelite odobrenje za kreiranje vidžeta i pristup njihovim podacima." "Nisu postavljene zadane vrijednosti." "Obriši zadane vrijednosti" "Ova aplikacija možda nije dizajnirana za vaš ekran. Ovdje možete odrediti kako se ona prilagođava vašem ekranu." @@ -1932,7 +1933,7 @@ "Magenta" "Koristiti %1$s?" "Usluga %1$s treba da:" - "Aplikacija nije dala dozvolu za zahtjev pa postavke ne mogu potvrditi vaš odgovor." + "Aplikacija nije dala odobrenje za zahtjev pa postavke ne mogu potvrditi vaš odgovor." "Ukoliko uključite uslugu %1$s, uređaj neće koristiti zaključavanje ekrana za poboljšanje šifriranja podataka." "Pošto ste uključili uslugu pristupačnosti, vaš uređaj neće koristiti zaključavanje ekrana za poboljšanje šifriranja podataka." "Uključivanje usluge %1$s utiče na šifriranje podataka, stoga je potrebno da potvrdite svoj obrazac." @@ -2653,7 +2654,7 @@ "Historija poziva i SMS-ova će se dijeliti s ovim korisnikom." "Informacije za hitne slučajeve" "Informacije i kontakti za korisnika %1$s" - "Dozvole za aplikacije i sadržaj" + "Odobrenja za aplikacije i sadržaj" "Aplikacije s ograničenjima" "Proširi postavke za aplikaciju" "Ova postavka utiče na sve korisnike ovog tableta." @@ -2819,7 +2820,7 @@ "hitni slučajevi, led, aplikacija, zadano" "telefon, brojčanik, zadani" "aplikacije, preuzimanje, aplikacije, sistem" - "aplikacije, dozvole, sigurnost" + "aplikacije, odobrenja, sigurnost" "aplikacije, zadane" "ignorirati optimizacije, doziranje, stanje mirovanja aplikacije" "jarke, RGB, sRGB, boja, prirodno, standardo" @@ -3250,7 +3251,7 @@ "Nema potrošnje baterije od prošlog potpunog punjenja" "Postavke aplikacije" "Prikaži podešivač za SystemUI" - "Dodatne dozvole" + "Dodatna odobrenja" "Još %1$d" "Podijeliti izvještaj o grešci?" "Vaš IT administrator je zatražio izvještaj o grešci kako bi pomogao u rješavanju problema ovog uređaja. Može doći do dijeljenja aplikacija i podataka." @@ -3325,7 +3326,7 @@ "Aplikacije" "Prikaz preko drugih aplikacija" "Dozvoli prikaz preko drugih aplikacija" - "Dozvola za prikaz aplikacije iznad svih" + "Odobrenje za prikaz aplikacije iznad svih" "Dozvolite ovoj aplikaciji da prekrije ostale aplikacije koje koristite. Može vas ometati u korištenju tih aplikacija ili promijeniti način na koji se one prikazuju ili ponašaju." "vr slušalac virtuelne realnosti stereo pomoćna usluga" "sistem upozorenje prozor dijaloški okvir prikazivanje preko drugih aplikacija" @@ -3342,7 +3343,7 @@ "Mogu mijenjati postavke sistema" "Mogu mijenjati postavke sistema" "Izmjeni postavke sistema" - "Dozvola za izmjenu postavki sistema aplikacije" + "Odobrenje za izmjenu postavki sistema aplikacije" "Dozvoli izmijenu postavki sistema" "Ovo odobrenje omogućava aplikaciji da izmijeni postavke sistema." "Da" @@ -3442,8 +3443,6 @@ "Koristite hladnije boje prikaza" "Isključite ekran kako biste primijenili promjenu boje" "Da primijenite promjenu na nadzoru telefonije, ponovo pokrenite uređaj" - "Kamera HAL HDR+" - "Da primijenite promjenu za Kamera HAL HDR+, ponovo pokrenite uređaj" "Laserski senzor kamere" "Automatsko ažuriranje sistema" "Potrošnja" @@ -3548,7 +3547,7 @@ "Podrška i savjeti" "Najmanja širina" "Nijedna instalirana aplikacija nije zatražila pristup premijum SMS-ovima" - "Usluga Premium SMS se možda dodatno plaća te će trošak biti na računu koji dobijate od operatera. Ukoliko aplikaciji date dozvolu, moći ćete slati premium SMS poruke putem te aplikacije." + "Usluga Premium SMS se možda dodatno plaća te će trošak biti na računu koji dobijate od operatera. Ukoliko aplikaciji date odobrenje, moći ćete slati premium SMS poruke putem te aplikacije." "Pristup premijum SMS-ovima" "Isključeno" "Povezan s uređajem %1$s" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 20fbac81c1e..c4a60c60e9d 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -624,14 +624,15 @@ "Per vincular amb:<br><b>%1$s</b><br><br>Assegura\'t que apareix aquesta contrasenya:<br><b>%2$s</b>" "De:<br><b>%1$s</b><br><br>Vols vincular-lo amb aquest dispositiu?" "Per vincular amb:<br><b>%1$s</b><br><br>Escriu <br><b>%2$s</b> en el dispositiu i, a continuació, prem la tecla de retorn." - "Permet que %1$s accedeixi als contactes i a l\'historial de trucades" + + "No s\'ha pogut connectar amb %1$s." "Cerca dispositius" "Actualitza" "S\'està cercant..." "Configuració del dispositiu" - "Dispositiu emparellat" + "Dispositiu vinculat" "Nom" "Connexió a Internet" "Teclat" @@ -668,7 +669,7 @@ "L\'accés a Internet mitjançant %1$s es desconnectarà." "%1$s es desconnectarà de la compartició de la connexió a Internet de la tauleta." "%1$s es desconnectarà i no compartirà la connexió a Internet del telèfon." - "Dispositiu Bluetooth emparellat" + "Dispositiu Bluetooth vinculat" "Connecta" "Connecta\'t al dispositiu Bluetooth" "S\'utilitza per" @@ -1558,7 +1559,7 @@ "El telèfon i les dades personals són més vulnerables a atacs d\'aplicacions desconegudes. En instal·lar aplicacions d\'aquesta font, acceptes que ets responsable de qualsevol dany al telèfon i qualsevol pèrdua de dades que es pugui produir per l\'ús d\'aquestes aplicacions." "Configuració avançada" "Activa més opcions de configuració" - "Informació de l\'aplicació" + "Informació de les aplicacions" "Emmagatzematge" "Obrir de manera determinada" "Valors predeterminats" @@ -1649,7 +1650,7 @@ "Mou a la tauleta" "Desplaça al telèfon" "Mou a emmagatzematge USB" - "Desplaça a la targeta SD" + "Mou a la targeta SD" "S\'està desplaçant" "Ja hi ha una migració en curs." "No hi ha prou espai d\'emmagatzematge." @@ -3400,8 +3401,6 @@ "Utilitza colors de pantalla més freds" "Desactiva la pantalla per aplicar el canvi de color" "Per aplicar canvis al monitor de telefonia, reinicia el dispositiu" - "HDR+ a HAL de la càmera" - "Per aplicar els canvis de HDR+ de HAL de la càmera, reinicia el dispositiu" "Sensor del làser de la càmera" "Actualitzacions del sistema automàtiques" "Ús" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 6633a94d882..74d00395352 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -624,7 +624,8 @@ ) --> "Von:<br><b>%1$s</b><br><br> Mit diesem Gerät koppeln?" "Gib zur Kopplung mit <br><b>%1$s</b><br><br> <br><b>%2$s</b> ein und drücke anschließend die Eingabetaste." - "Zulassen, dass %1$s auf deine Kontakte und deine Anrufliste zugreifen kann" + + "Keine Verbindung zu %1$s möglich" "Scan nach Geräten" @@ -3058,7 +3059,7 @@ "An" "Aus" "Bildschirmfixierung" - "Wenn diese Einstellung aktiviert ist, kannst du die Ansicht des aktuellen Bildschirms fixieren.\n\nSo geht\'s:\n\n1. Prüfe, ob die Bildschirmfixierung aktiviert ist.\n\n2. Öffne den Bildschirm, den du fixieren möchtest.\n\n3. Tippe auf \"Übersicht\".\n\n4. Wische nach oben und tippe auf das Stecknadelsymbol." + "Wenn diese Einstellung aktiviert ist, kannst du die Ansicht des aktuellen Bildschirms fixieren.\n\nSo gehts:\n\n1. Prüfe, ob die Bildschirmfixierung aktiviert ist.\n\n2. Öffne den Bildschirm, den du fixieren möchtest.\n\n3. Tippe auf \"Übersicht\".\n\n4. Wische nach oben und tippe auf das Stecknadelsymbol." "Vor dem Beenden nach Entsperrungsmuster fragen" "Vor Beenden nach PIN fragen" "Vor dem Beenden nach Passwort fragen" @@ -3310,7 +3311,7 @@ "Nein" "Dieser Quelle vertrauen" "Zum Öffnen der Kamera zweimal drehen" - "Kamera App durch zweimaliges Drehen des Handgelenks öffnen" + "Kamera-App durch zweimaliges Drehen des Handgelenks öffnen" "Für Kamera Ein/Aus zweimal drücken" "Kamera ohne Entsperren des Displays schnell öffnen" "Anzeigegröße" @@ -3400,8 +3401,6 @@ "Kältere Displayfarben verwenden" "Deaktiviere den Bildschirm, um die neue Farbeinstellung zu übernehmen" "Gerät neu starten, damit die Änderungen bei Telephony Monitor wirksam werden" - "Kamera HAL HDR+" - "Gerät neu starten, damit die Änderungen bei Kamera HAL HDR+ wirksam werden" "Kamera-Lasersensor" "Automatische Systemupdates" "Nutzung" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 59dd423bd2a..fbf1fbfbee8 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -624,7 +624,8 @@ "‏برای مرتبط‌سازی با:<br><b>%1$s</b><br><br>مطمئن شوید که دستگاه این کلیدواژه را نمایش می‌دهد:<br><b>%2$s</b>" "‏از::<br><b>%1$s</b><br><br>با این دستگاه مرتبط‌سازی شود؟" "‏برای مرتبط‌سازی با:<br><b>%1$s</b><br><br>روی آن تایپ کنید:<br><b>%2$s</b>، سپس Return یا Enter را فشار دهید." - "به %1$s اجازه داده شود به مخاطبین و سابقه تماس شما دسترسی داشته باشد" + + "اتصال به %1$s ممکن نیست." "اسکن برای دستگاه‌ها" @@ -3400,8 +3401,6 @@ "استفاده از رنگ‌های سردتر نمایشگر" "برای اعمال تغییر رنگ، صفحه را خاموش کنید" "‏برای اعمال تغییر Telephony Monitor، دستگاه را راه‌اندازی مجدد کنید" - "‏دوربین HAL HDR+‎" - "‏برای اعمال تغییر دوربین HAL HDR+‎، دستگاه را راه‌اندازی مجدد کنید" "حسگر لیزری دوربین" "به‌روزرسانی‌های خودکار سیستم" "میزان مصرف" @@ -3474,7 +3473,7 @@ "هدف" "حذف هدف" "هدف تمام صفحه" - "فعالیت‌ها" + "کنش‌ها" "عنوان" "ورودی‌های از راه دور" "نمای سفارشی" @@ -3511,8 +3510,8 @@ "حالت نمایشی رابط کاربری سیستم" "کاشی‌های برنامه‌نویسی تنظیمات سریع" "ما اینجاییم تا به شما کمک کنیم" - "۲۴ ساعت روز/۷ روز هفته آماده کمک به شما هستیم" - "۲۴ ساعت روز/۷ روز هفته آماده کمک به شما هستیم" + "۲۴ساعته و ۷روزهفته آماده کمک به شما هستیم" + "۲۴ساعته و ۷روزهفته آماده کمک به شما هستیم" "تیم پشتیبانی ما اینجاست تا در رسیدگی به هر مشکلی کمک کند" "تیم پشتیبانی ما به‌صورت شبانه‌روزی دردسترس است" "‏راهنما را جستجو کنید یا در ساعات کاری پشتیبانی (به‌وقت محلی) تماس بگیرید:<br><b>%s</b>" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 12d42a7455c..e837e8e5bf3 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -624,7 +624,8 @@ "यासह जोडण्यासाठी:<br><b>%1$s</b><br><br>हे ही पासकी दर्शवत असल्याचे सुनिश्चित करा:<br><b>%2$s</b>" "यावरून:<br><b>%1$s</b><br><br>हे डिव्हाइस जोडायचे?" "यासह जोडण्यासाठी:<br><b>%1$s</b><br><br>यावर टाइप करा:<br><b>%2$s</b>, नंतर Return किंवा Enter दाबा." - "%1$s ला आपले संपर्क आणि कॉल इतिहासामध्‍ये प्रवेश करण्‍याची अनुमती द्या" + + "%1$s सह कनेक्ट करणे शक्य झाले नाही." "डिव्हाइसेससाठी स्कॅन करा" @@ -2636,16 +2637,16 @@ "भाषा बदला" "टॅप करा आणि पे करा" "हे कसे कार्य करते" - "दुकानांमध्‍ये आपल्‍या फोनद्वारे देयक द्या" - "देयक डीफॉल्ट" + "दुकानांमध्‍ये आपल्‍या फोनद्वारे पेमेंट द्या" + "पेमेंट डीफॉल्ट" "सेट केले नाही" "%1$s - %2$s" "डीफॉल्ट वापरा" "नेहमी" - "दुसरा देयक अॅप खुला असतो तेव्हा त्यास वगळून" + "दुसरा पेमेंट अॅप खुला असतो तेव्हा त्यास वगळून" "टॅप आणि पे टर्मिनलवर, यासह पे करा:" "टर्मिनलवर देय द्या" - "देयक अॅप सेट करा. त्यानंतर संपर्करहित आयकन असलेल्या कोणत्याही टर्मिनलवर आपल्‍या फोनची मागील बाजू धरा." + "पेमेंट अॅप सेट करा. त्यानंतर संपर्करहित आयकन असलेल्या कोणत्याही टर्मिनलवर आपल्‍या फोनची मागील बाजू धरा." "समजले" "आणखी..." "आपले प्राधान्य म्हणून सेट करायचे?" @@ -3400,8 +3401,6 @@ "आणखी छान डिस्प्ले रंग वापरा" "रंग बदल लागू करण्यासाठी, स्क्रीन बंद करा" "टेलिफोनी मॉनिटर बदल लागू करण्‍यासाठी, डिव्हाइस रीबूट करा" - "कॅमेरा HAL HDR+" - "कॅमेरा HAL HDR+ बदल लागू करण्यासाठी डिव्हाइस रीबूट करा" "कॅमेरा लेझर सेंसर" "स्वयंचलित सिस्टम अपडेट" "वापर" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 861cba31628..9c2004abb63 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -25,8 +25,8 @@ "Alternar" "Desconhecido" - Está agora a %1$d passo de se tornar um programador. Está agora a %1$d passos de se tornar um programador. + Está agora a %1$d passo de se tornar um programador. "Agora é um programador!" "Não é necessário, já é um programador." @@ -254,8 +254,8 @@ "Remover" "Adicionar um idioma" - Pretende remover o idioma selecionado? Pretende remover os idiomas selecionados? + Pretende remover o idioma selecionado? "O texto será apresentado noutro idioma." "Não é possível remover todos os idiomas" @@ -359,8 +359,8 @@ "Adicionar impressão digital" "bloqueio de ecrã" - %1$d impressão digital configurada %1$d impressões digitais configuradas + %1$d impressão digital configurada "Desbloq. com impressão digital" @@ -564,28 +564,28 @@ "Tem de incluir, pelo menos, um dígito" "Tem de incluir, pelo menos, um símbolo" - Tem de incluir, pelo menos, 1 letra Tem de incluir, pelo menos, %d letras + Tem de incluir, pelo menos, 1 letra - Tem de incluir, pelo menos, 1 letra minúscula Tem de incluir, pelo menos, %d letras minúsculas + Tem de incluir, pelo menos, 1 letra minúscula - Tem de incluir, pelo menos, 1 letra maiúscula Tem de incluir, pelo menos, %d letras maiúsculas + Tem de incluir, pelo menos, 1 letra maiúscula - Tem de incluir, pelo menos, 1 dígito numérico Tem de incluir, pelo menos, %d dígitos numéricos + Tem de incluir, pelo menos, 1 dígito numérico - Tem de incluir, pelo menos, 1 símbolo especial Tem de incluir, pelo menos, %d símbolos especiais + Tem de incluir, pelo menos, 1 símbolo especial - Tem de incluir, pelo menos, 1 caráter que não seja uma letra Tem de incluir, pelo menos, %d carateres que não sejam letras + Tem de incluir, pelo menos, 1 caráter que não seja uma letra "O admin. do disp. não permite a utilização de uma palavra-passe recente" "Não é permitida uma sequência de dígitos ascendente, descendente ou repetida" @@ -598,15 +598,15 @@ "Aplicações de gestor do dispositivo" "Sem aplicações ativas" - %d aplicação ativa %d aplicações ativas + %d aplicação ativa "Agentes fidedignos" "Para utilizar, defina primeiro um bloqueio de ecrã" "Nenhum" - 1 agente fidedigno ativo %d agentes fidedignos ativos + 1 agente fidedigno ativo "Bluetooth" "Ativar Bluetooth" @@ -624,7 +624,8 @@ "Para sincronizar com: <br><b>%1$s</b><br><br>Verifique se apresenta esta chave de acesso: <br><b>%2$s</b>" "De: <br><b>%1$s</b><br><br> Sincronizar com este aparelho?" "Para sincronizar com:<br><b>%1$s</b><br><br>Introduza no mesmo:<br><b>%2$s</b> e, em seguida, prima Enter." - "Permitir que o dispositivo %1$s aceda aos contactos e ao histórico de chamadas" + + "Não foi possível ligar a %1$s." "Procurar dispositivos" @@ -847,8 +848,8 @@ "Cancelar" "Redes guardadas" - 1 rede %d redes + 1 rede "Wi-Fi Avançada" "Endereço MAC" @@ -1116,8 +1117,8 @@ "O %1$s é o único cartão SIM no dispositivo. Pretende utilizar este cartão SIM para os dados móveis, as chamadas e as mensagens SMS?" "Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo." - Código PIN incorreto. Tem mais %d tentativa antes de ter de contactar operador p/ desbloquear dispos. Código PIN do cartão SIM incorreto. Tem mais %d tentativas. + Código PIN incorreto. Tem mais %d tentativa antes de ter de contactar operador p/ desbloquear dispos. "Falha ao introduzir o PIN do cartão SIM!" "Estado do tablet" @@ -1568,8 +1569,8 @@ "Limpar cache" "Cache" - 1 item %d itens + 1 item "Limpar acesso" "Controlos" @@ -1859,24 +1860,24 @@ "Mostrar nas Definições rápidas" "Modo de correção" - Atraso extremamente curto (%1$d ms) Atraso extremamente curto (%1$d ms) + Atraso extremamente curto (%1$d ms) - Atraso muito curto (%1$d ms) Atraso muito curto (%1$d ms) + Atraso muito curto (%1$d ms) - Atraso curto (%1$d ms) Atraso curto (%1$d ms) + Atraso curto (%1$d ms) - Atraso longo (%1$d ms) Atraso longo (%1$d ms) + Atraso longo (%1$d ms) - Atraso muito longo (%1$d ms) Atraso muito longo (%1$d ms) + Atraso muito longo (%1$d ms) "Configurações" "Ativado" @@ -1930,12 +1931,12 @@ "Impressão" "Desativado" - 1 serviço de impressão ativado %1$d serviços de impressão ativados + 1 serviço de impressão ativado - 1 tarefa de impressão %1$d tarefas de impressão + 1 tarefa de impressão "Serviços de impressão" "Nenhum serviço instalado" @@ -2551,21 +2552,21 @@ "A rede pode ser monitorizada" "Concluído" - Confiar ou remover o certificado Confiar ou remover os certificados + Confiar ou remover o certificado - %s instalou uma autoridade de certificação no seu dispositivo que pode permitir monitorizar a atividade na rede do dispositivo, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca deste certificado, contacte o gestor. %s instalou autoridades de certificação no seu dispositivo que podem permitir monitorizar a atividade na rede do dispositivo, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca destes certificados, contacte o gestor. + %s instalou uma autoridade de certificação no seu dispositivo que pode permitir monitorizar a atividade na rede do dispositivo, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca deste certificado, contacte o gestor. - %s instalou uma autoridade de certificação para o seu perfil de trabalho que pode permitir monitorizar a atividade na rede de trabalho, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca deste certificado, contacte o gestor. %s instalou autoridades de certificação para o seu perfil de trabalho que podem permitir monitorizar a atividade na rede de trabalho, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca destes certificados, contacte o gestor. + %s instalou uma autoridade de certificação para o seu perfil de trabalho que pode permitir monitorizar a atividade na rede de trabalho, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca deste certificado, contacte o gestor. "A sua atividade de rede, incluindo emails, aplicações e Sites seguros, pode ser monitorizada por terceiros.\n\nIsto é possível através de uma credencial fidedigna instalada no seu dispositivo." - Verificar certificado Verificar certificados + Verificar certificado "Utilizadores" "Utilizadores e perfis" @@ -2742,8 +2743,8 @@ "A seleção é necessária" "Definições" - Mostrar %d item oculto Mostrar %d itens ocultos + Mostrar %d item oculto "Rede e Internet" "rede móvel" @@ -2844,8 +2845,8 @@ "Ativar sons" "Nenhuma regra automática ativada" - 1 regra automática ativada %d regras automáticas ativadas + 1 regra automática ativada "Preferências de Não incomodar" "Prioridade permite apenas" @@ -2913,8 +2914,8 @@ "O acesso às notificações do perfil de trabalho está bloqueado" "As aplicações não podem ler notificações" - %d aplicação pode ler notificações %d aplicações podem ler notificações + %d aplicação pode ler notificações "Nenhuma aplicação instalada solicitou acesso a notificações" "Pretende permitir o acesso a notificações de %1$s?" @@ -2946,12 +2947,12 @@ "Definições adicionais na aplicação" "Ativadas para todas as aplicações" - Desativado para %d aplicação Desativado para %d aplicações + Desativado para %d aplicação - %d categoria eliminada %d categorias eliminadas + %d categoria eliminada "Ativadas" "Desativadas" @@ -3034,12 +3035,12 @@ "%s do dia seguinte" "Alterar para alarmes apenas, indefinidamente" - Alterar para alarmes apenas durante um minuto até à(s) %2$s Alterar para alarmes apenas durante %1$d minutos (até à(s) %2$s) + Alterar para alarmes apenas durante um minuto até à(s) %2$s - Alterar para alarmes apenas durante uma hora até à(s) %2$s Alterar para alarmes apenas durante %1$d horas até à(s) %2$s + Alterar para alarmes apenas durante uma hora até à(s) %2$s "Alterar para alarmes apenas, até %1$s" "Alterar para interromper sempre" @@ -3112,16 +3113,16 @@ "Nível %d" "%1$s%2$s" - %d autorização concedida %d autorizações concedidas + %d autorização concedida - %d de %d autorização concedida %d de %d autorizações concedidas + %d de %d autorização concedida - %d permissão adicional %d permissões adicionais + %d permissão adicional "Nenhuma permissão concedida" "Nenhuma permissão solicitada" @@ -3149,8 +3150,8 @@ "Abrir %s e outros URLs" "Nenhum aplicação abre links compatíveis" - Uma aplicação que abre links compatíveis %d aplicações que abrem links compatíveis + Uma aplicação que abre links compatíveis "Abrir com esta aplicação" "Perguntar sempre" @@ -3193,12 +3194,12 @@ "Mostrar utilização de aplic." "Utilização elevada" - %1$s aplicação está a apresentar um comportamento anormal %2$d aplicações estão a apresentar um comportamento anormal + %1$s aplicação está a apresentar um comportamento anormal - %1$s a consumir rapidamente a bateria Aplicações a consumir rapidamente a bateria + %1$s a consumir rapidamente a bateria "Não otimizada" "Não otimizada" @@ -3262,8 +3263,8 @@ "Disponível" "Memória utilizada pelas aplicações" - 1 aplicação utilizou a memória nos(as) últimos(as) %2$s %1$d aplicações utilizaram a memória nos(as) últimos(as) %2$s + 1 aplicação utilizou a memória nos(as) últimos(as) %2$s "Frequência" "Utilização máxima" @@ -3333,8 +3334,8 @@ "Sem ligação" "%1$s dos dados utilizados" - Desativadas para 1 aplicação Desativadas para %d aplicações + Desativadas para 1 aplicação "Ativadas para todas as aplicações" "%1$d aplicações instaladas" @@ -3388,20 +3389,18 @@ "+%1$d" "Mais %1$d" - 1 sugestão %1$d sugestões + 1 sugestão - Mais 1 sugestão Mais %1$d sugestões + Mais 1 sugestão "Remover" "Temperatura da cor fria" "Utilizar cores de visualização mais frias" "Para aplicar uma alteração de cor, desligue o ecrã" "Para aplicar a alteração ao Monitor de telefonia, reinicie o dispositivo" - "Câmara HAL HDR+" - "Para aplicar a alteração da Câmara HAL HDR+, reinicie o dispositivo." "Sensor de laser da câmara" "Atualizações do sistema automáticas" "Utilização" @@ -3419,8 +3418,8 @@ "Mensalmente no dia %1$s" "Restrições de rede" - 1 restrição %1$d restrições + 1 restrição "A contagem de dados do operador pode ser diferente da contagem do dispositivo" "%1$s utilizado(s)" @@ -3432,8 +3431,8 @@ "Configurar" "Outras aplicações incluídas na utilização" - 1 aplicação autorizada a utilizar dados sem restrições quando a Poupança de dados está ativada %1$d aplicações autorizadas a utilizar dados sem restrições quando a Poupança de dados está ativada + 1 aplicação autorizada a utilizar dados sem restrições quando a Poupança de dados está ativada "Poupança de dados" "Dados sem restrições" @@ -3490,8 +3489,8 @@ "O objeto de classificação não contém esta chave." "Acesso especial a aplicações" - 1 aplicação pode utilizar dados sem restrições %d aplicações podem utilizar dados sem restrições + 1 aplicação pode utilizar dados sem restrições "Pretende mesmo limpar os dados do utilizador e converter para a encriptação de ficheiros?" "Limpar e converter" @@ -3539,16 +3538,16 @@ "Pesquisa de contactos" "Permitir pesquisa de contactos por parte da sua entidade para identificar autores das chamadas e contactos" - 1 hora %s horas + 1 hora - 1 minuto %s minutos + 1 minuto - 1 segundo %s segundos + 1 segundo "Tempo de espera de ~%1$s" "Computador" @@ -3637,16 +3636,16 @@ "Aplicações instaladas" "O número de aplicações é uma estimativa. Pode não incluir as aplicações instaladas fora da Play Store." - No mínimo, %d aplicação No mínimo, %d aplicações + No mínimo, %d aplicação "Autorizações de acesso à localização" "Autorizações do microfone" "Autorizações da câmara" "Aplicações predefinidas" - %d aplicação %d aplicações + %d aplicação "Teclado predefinido" "Definido como %s" @@ -3658,35 +3657,35 @@ "Credenciais fidedignas no seu perfil pessoal" "Credenciais fidedignas no seu perfil de trabalho" - No mínimo, %d certificado da AC No mínimo, %d certificados da AC + No mínimo, %d certificado da AC "O gestor pode bloquear o dispositivo e repor a palavra-passe" "O gestor pode eliminar todos os dados do dispositivo" "Tentativas de introdução da palavra-passe falhadas antes da eliminação de todos os dados do dispositivo" "Tentativas de introdução da palavra-passe falhadas antes da eliminação de todos os dados do perfil de trabalho" - %d tentativa %d tentativas + %d tentativa "Este dispositivo é gerido pela sua entidade." "Este dispositivo é gerido por %s." " " "Saiba mais" - Aplicação de câmara Aplicações de câmara + Aplicação de câmara "Aplicação de calendário" "Aplicação de contactos" - Aplicação de cliente de email Aplicações de cliente de email + Aplicação de cliente de email "Aplicação de mapas" - Aplicação de telefone Aplicações de telefone + Aplicação de telefone "%1$s, %2$s" "%1$s, %2$s, %3$s" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 5fb0dca230f..d927a20f8ab 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -646,7 +646,8 @@ "Щоб створити пару з пристроєм:<br><b>%1$s</b><br><br>Переконайтеся, що відображається цей ключ доступу:<br><b>%2$s</b>" "Від пристрою:<br><b>%1$s</b><br><br>Створити пару з цим пристроєм?" "Щоб створити пару з пристроєм: <br><b>%1$s</b><br><br> Введіть на ньому: <br><b>%2$s</b>, а потім натисніть \"Повернутися\" або \"Ввійти\"." - "Надати пристрою %1$s доступ до контактів та історії дзвінків" + + "Не вдалося з’єднатися з пристроєм %1$s." "Сканув. пристроїв" @@ -3233,7 +3234,7 @@ "Помічник і голосовий ввід" "Додаток-помічник" "Зробити додаток %s помічником?" - "Помічник матиме доступ до інформації про додатки у вашій системі, зокрема до даних на екрані та в додатках." + "Асистент матиме доступ до інформації про додатки у вашій системі, зокрема до даних на екрані та в додатках." "Прийняти" "Не приймати" "Вибрати голосовий ввід" @@ -3484,8 +3485,6 @@ "Використовувати холодніші кольори дисплея" "Щоб змінити кольори, вимкніть екран" "Щоб застосувати зміни у функції Telephony Monitor, перезапустіть пристрій" - "Режим HDR+ на рівні HAL камери" - "Щоб зміна режиму HDR+ на рівні HAL камери почала діяти, перезапустіть пристрій" "Лазерний датчик камери" "Автоматичне оновлення системи" "Використання" From 3ed385256aaffa7ee653e264bc14b844fb545ee0 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 7 Dec 2017 17:08:40 -0800 Subject: [PATCH 10/13] Import translations. DO NOT MERGE Auto-generated-cl: translation import Bug: 64712476 Change-Id: I35a94b9a271e88bf4f0384d5619c59661516131d --- res/values-bs/strings.xml | 33 +++++----- res/values-ca/strings.xml | 11 ++-- res/values-de/strings.xml | 7 ++- res/values-fa/strings.xml | 9 +-- res/values-mr/strings.xml | 11 ++-- res/values-pt-rPT/strings.xml | 115 +++++++++++++++++----------------- res/values-uk/strings.xml | 5 +- 7 files changed, 99 insertions(+), 92 deletions(-) diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index b07d78114f9..9878e9e800b 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -54,7 +54,7 @@ "Nije registrirano" "Dostupno" "Nedostupno" - "IMS registracija: %1$s\nGovor putem LTE mreže: %2$s\nGovor putem Wi-Fi mreže: %3$s\nVideo pozivanje: %4$s\nUT sučelje: %5$s" + "IMS registracija: %1$s\nGovor putem LTE mreže: %2$s\nGovor putem Wi-Fi mreže: %3$s\nVideo pozivanje: %4$s\nUT interfejs: %5$s" "Aktivan" "Ne radi" "Samo pozivi za hitne slučajeve" @@ -114,7 +114,7 @@ "Vaš tablet će prekinuti vezu s uređajem %1$s." "Vaš uređaj će prekinuti vezu s uređajem %1$s." "Prekini vezu" - "Nemate dozvolu da mijenjate postavke za Bluetooth." + "Nemate odobrenje da mijenjate postavke za Bluetooth." "Uparivanje novog uređaja" "Uređaj %1$s je vidljiv uređajima u blizini, dok su postavke Bluetootha otvorene." "Bluetooth adresa telefona: %1$s" @@ -629,7 +629,8 @@ "Da biste izvršilu uparivanje s uređajem:<br><b>%1$s</b><br><br>Provjerite da li se prikazuje sljedeći pristupni ključ:<br><b>%2$s</b>" "Od:<br><b>%1$s</b><br><br>Želite izvršiti uparivanje s ovim uređajem?" "Da biste izvršili uparivanje s uređajem:<br><b>%1$s</b><br><br>Otkucajte na njemu:<br><b>%2$s</b>, a zatim pritisnite Return ili Enter." - "Dozvoli uređaju %1$s pristup mojim kontaktima i istoriji poziva" + + "Nije uspjelo povezivanje sa uređajem %1$s." "Potraži uređaje" @@ -772,7 +773,7 @@ "Piši na NFC oznake" "Da biste vidjeli dostupne mreže, uključite Wi-Fi." "Traži se Wi-Fi mreža..." - "Nemate dozvolu za promjenu Wi-Fi mreže." + "Nemate odobrenje za promjenu Wi-Fi mreže." "Još" "Autom. postavljanje (WPS)" "Napredne opcije" @@ -813,7 +814,7 @@ "Opseg od 2.4 GHz" "Opseg od 5 GHz" "IP postavke" - "Podijeli s ostalim korisnicima uređaja" + "Dijeli s ostalim korisnicima uređaja" "(nepromijenjeno)" "Odaberite" "(dodano je više certifikata)" @@ -1399,7 +1400,7 @@ "Dijeljenje internetske veze tableta putem Bluetootha" "Dijeljenje internetske veze telefona putem Bluetootha" "Dijeljenje internetske veze uređaja %1$d putem Bluetootha" - "Ne može se povezati sa više od %1$d uređaja." + "Nije se moguće povezati sa više od %1$d uređaja." "Prestat će se dijeliti veza s uređajem %1$s." "Koristite pristupnu tačku i dijeljenje veze za pružanje interneta drugim uređajima putem mobilnog prijenosa podataka. Aplikacije također mogu kreirati pristupne tačke za dijeljenje sadržaja s uređajima u blizini." "Pomoć" @@ -1452,7 +1453,7 @@ "Lokacija i Google pretraživanje" "Dopustite da Google koristi vašu lokaciju radi poboljšavanja rezultata pretraživanja i drugih usluga" "Pristup mojoj lokaciji" - "Dopustite aplikacijama koje su zatražile vašu dozvolu da koriste informacije o vašoj lokaciji" + "Dopustite aplikacijama koje su zatražile vaše odobrenje da koriste informacije o vašoj lokaciji" "Izvori lokacije" "O tabletu" "O telefonu" @@ -1564,7 +1565,7 @@ "Zadano otvori" "Zadane vrijednosti" "Kompatibilnost ekrana" - "Dozvole" + "Odobrenja" "Keš" "Obriši keš memoriju" "Keš" @@ -1590,7 +1591,7 @@ "Obriši podatke" "Deinstaliraj ažuriranja" "Odabrali ste zadano pokretanje ove aplikacije za neke radnje." - "Odabrali ste da ovoj aplikaciji dodijelite dozvolu za kreiranje vidžeta i pristup njihovim podacima." + "Odabrali ste da ovoj aplikaciji dodijelite odobrenje za kreiranje vidžeta i pristup njihovim podacima." "Nisu postavljene zadane vrijednosti." "Obriši zadane vrijednosti" "Ova aplikacija možda nije dizajnirana za vaš ekran. Ovdje možete odrediti kako se ona prilagođava vašem ekranu." @@ -1928,7 +1929,7 @@ "Magenta" "Koristiti %1$s?" "Usluga %1$s treba da:" - "Aplikacija nije dala dozvolu za zahtjev pa postavke ne mogu potvrditi vaš odgovor." + "Aplikacija nije dala odobrenje za zahtjev pa postavke ne mogu potvrditi vaš odgovor." "Ukoliko uključite uslugu %1$s, uređaj neće koristiti zaključavanje ekrana za poboljšanje šifriranja podataka." "Pošto ste uključili uslugu pristupačnosti, vaš uređaj neće koristiti zaključavanje ekrana za poboljšanje šifriranja podataka." "Uključivanje usluge %1$s utiče na šifriranje podataka, stoga je potrebno da potvrdite svoj obrazac." @@ -2645,7 +2646,7 @@ "Historija poziva i SMS-ova će se dijeliti s ovim korisnikom." "Informacije za hitne slučajeve" "Informacije i kontakti za korisnika %1$s" - "Dozvole za aplikacije i sadržaj" + "Odobrenja za aplikacije i sadržaj" "Aplikacije s ograničenjima" "Proširi postavke za aplikaciju" "Ova postavka utiče na sve korisnike ovog tableta." @@ -2811,7 +2812,7 @@ "hitni slučajevi, led, aplikacija, zadano" "telefon, brojčanik, zadani" "aplikacije, preuzimanje, aplikacije, sistem" - "aplikacije, dozvole, sigurnost" + "aplikacije, odobrenja, sigurnost" "aplikacije, zadane" "ignorirati optimizacije, doziranje, stanje mirovanja aplikacije" "jarke, RGB, sRGB, boja, prirodno, standardo" @@ -3241,7 +3242,7 @@ "Nema potrošnje baterije od prošlog potpunog punjenja" "Postavke aplikacije" "Prikaži podešivač za SystemUI" - "Dodatne dozvole" + "Dodatna odobrenja" "Još %1$d" "Podijeliti izvještaj o grešci?" "Vaš IT administrator je zatražio izvještaj o grešci kako bi pomogao u rješavanju problema ovog uređaja. Može doći do dijeljenja aplikacija i podataka." @@ -3315,7 +3316,7 @@ "Aplikacije" "Prikaz preko drugih aplikacija" "Dozvoli prikaz preko drugih aplikacija" - "Dozvola za prikaz aplikacije iznad svih" + "Odobrenje za prikaz aplikacije iznad svih" "Dozvolite ovoj aplikaciji da prekrije ostale aplikacije koje koristite. Može vas ometati u korištenju tih aplikacija ili promijeniti način na koji se one prikazuju ili ponašaju." "vr slušalac virtuelne realnosti stereo pomoćna usluga" "sistem upozorenje prozor dijaloški okvir prikazivanje preko drugih aplikacija" @@ -3332,7 +3333,7 @@ "Mogu mijenjati postavke sistema" "Mogu mijenjati postavke sistema" "Izmjeni postavke sistema" - "Dozvola za izmjenu postavki sistema aplikacije" + "Odobrenje za izmjenu postavki sistema aplikacije" "Dozvoli izmijenu postavki sistema" "Ovo odobrenje omogućava aplikaciji da izmijeni postavke sistema." "Da" @@ -3533,7 +3534,7 @@ "Podrška i savjeti" "Najmanja širina" "Nijedna instalirana aplikacija nije zatražila pristup premijum SMS-ovima" - "Usluga Premium SMS se možda dodatno plaća te će trošak biti na računu koji dobijate od operatera. Ukoliko aplikaciji date dozvolu, moći ćete slati premium SMS poruke putem te aplikacije." + "Usluga Premium SMS se možda dodatno plaća te će trošak biti na računu koji dobijate od operatera. Ukoliko aplikaciji date odobrenje, moći ćete slati premium SMS poruke putem te aplikacije." "Pristup premijum SMS-ovima" "Nije vidljivo drugim uređajima" "Povezan s uređajem %1$s" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index c275b45aca0..d6e991894b5 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -618,14 +618,15 @@ "Per vincular amb:<br><b>%1$s</b><br><br>Assegura\'t que apareix aquesta contrasenya:<br><b>%2$s</b>" "De:<br><b>%1$s</b><br><br>Vols vincular-lo amb aquest dispositiu?" "Per vincular amb:<br><b>%1$s</b><br><br>Escriu <br><b>%2$s</b> en el dispositiu i, a continuació, prem la tecla de retorn." - "Permet que %1$s accedeixi als contactes i a l\'historial de trucades" + + "No s\'ha pogut connectar amb %1$s." "Cerca dispositius" "Actualitza" "S\'està cercant..." "Configuració del dispositiu" - "Dispositiu emparellat" + "Dispositiu vinculat" "Nom" "Connexió a Internet" "Teclat" @@ -662,7 +663,7 @@ "L\'accés a Internet mitjançant %1$s es desconnectarà." "%1$s es desconnectarà de la compartició de la connexió a Internet de la tauleta." "%1$s es desconnectarà i no compartirà la connexió a Internet del telèfon." - "Dispositiu Bluetooth emparellat" + "Dispositiu Bluetooth vinculat" "Connecta" "Connecta\'t al dispositiu Bluetooth" "S\'utilitza per" @@ -1545,7 +1546,7 @@ "El telèfon i les dades personals són més vulnerables a atacs d\'aplicacions desconegudes. En instal·lar aplicacions d\'aquesta font, acceptes que ets responsable de qualsevol dany al telèfon i qualsevol pèrdua de dades que es pugui produir per l\'ús d\'aquestes aplicacions." "Configuració avançada" "Activa més opcions de configuració" - "Informació de l\'aplicació" + "Informació de les aplicacions" "Emmagatzematge" "Obrir de manera determinada" "Valors predeterminats" @@ -1636,7 +1637,7 @@ "Mou a la tauleta" "Desplaça al telèfon" "Mou a emmagatzematge USB" - "Desplaça a la targeta SD" + "Mou a la targeta SD" "S\'està desplaçant" "Ja hi ha una migració en curs." "No hi ha prou espai d\'emmagatzematge." diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 6576bf53505..181746db29a 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -618,7 +618,8 @@ ) --> "Von:<br><b>%1$s</b><br><br> Mit diesem Gerät koppeln?" "Gib zur Kopplung mit <br><b>%1$s</b><br><br> <br><b>%2$s</b> ein und drücke anschließend die Eingabetaste." - "Zulassen, dass %1$s auf deine Kontakte und deine Anrufliste zugreifen kann" + + "Keine Verbindung zu %1$s möglich" "Scan nach Geräten" @@ -3048,7 +3049,7 @@ "An" "Aus" "Bildschirmfixierung" - "Wenn diese Einstellung aktiviert ist, kannst du die Ansicht des aktuellen Bildschirms fixieren.\n\nSo geht\'s:\n\n1. Prüfe, ob die Bildschirmfixierung aktiviert ist.\n\n2. Öffne den Bildschirm, den du fixieren möchtest.\n\n3. Tippe auf \"Übersicht\".\n\n4. Wische nach oben und tippe auf das Stecknadelsymbol." + "Wenn diese Einstellung aktiviert ist, kannst du die Ansicht des aktuellen Bildschirms fixieren.\n\nSo gehts:\n\n1. Prüfe, ob die Bildschirmfixierung aktiviert ist.\n\n2. Öffne den Bildschirm, den du fixieren möchtest.\n\n3. Tippe auf \"Übersicht\".\n\n4. Wische nach oben und tippe auf das Stecknadelsymbol." "Vor dem Beenden nach Entsperrungsmuster fragen" "Vor Beenden nach PIN fragen" "Vor dem Beenden nach Passwort fragen" @@ -3299,7 +3300,7 @@ "Nein" "Dieser Quelle vertrauen" "Zum Öffnen der Kamera zweimal drehen" - "Kamera App durch zweimaliges Drehen des Handgelenks öffnen" + "Kamera-App durch zweimaliges Drehen des Handgelenks öffnen" "Für Kamera Ein/Aus zweimal drücken" "Kamera ohne Entsperren des Displays schnell öffnen" "Anzeigegröße" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 25a74cea9e4..de0003a42ba 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -618,7 +618,8 @@ "‏برای مرتبط‌سازی با:<br><b>%1$s</b><br><br>مطمئن شوید که دستگاه این کلیدواژه را نمایش می‌دهد:<br><b>%2$s</b>" "‏از::<br><b>%1$s</b><br><br>با این دستگاه مرتبط‌سازی شود؟" "‏برای مرتبط‌سازی با:<br><b>%1$s</b><br><br>روی آن تایپ کنید:<br><b>%2$s</b>، سپس Return یا Enter را فشار دهید." - "به %1$s اجازه داده شود به مخاطبین و سابقه تماس شما دسترسی داشته باشد" + + "اتصال به %1$s ممکن نیست." "اسکن برای دستگاه‌ها" @@ -3458,7 +3459,7 @@ "هدف" "حذف هدف" "هدف تمام صفحه" - "فعالیت‌ها" + "کنش‌ها" "عنوان" "ورودی‌های از راه دور" "نمای سفارشی" @@ -3495,8 +3496,8 @@ "حالت نمایشی رابط کاربری سیستم" "کاشی‌های برنامه‌نویسی تنظیمات سریع" "ما اینجاییم تا به شما کمک کنیم" - "۲۴ ساعت روز/۷ روز هفته آماده کمک به شما هستیم" - "۲۴ ساعت روز/۷ روز هفته آماده کمک به شما هستیم" + "۲۴ساعته و ۷روزهفته آماده کمک به شما هستیم" + "۲۴ساعته و ۷روزهفته آماده کمک به شما هستیم" "تیم پشتیبانی ما اینجاست تا در رسیدگی به هر مشکلی کمک کند" "تیم پشتیبانی ما به‌صورت شبانه‌روزی دردسترس است" "‏راهنما را جستجو کنید یا در ساعات کاری پشتیبانی (به‌وقت محلی) تماس بگیرید:<br><b>%s</b>" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index de48dec2d4e..8c0161b963b 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -618,7 +618,8 @@ "यासह जोडण्यासाठी:<br><b>%1$s</b><br><br>हे ही पासकी दर्शवत असल्याचे सुनिश्चित करा:<br><b>%2$s</b>" "यावरून:<br><b>%1$s</b><br><br>हे डिव्हाइस जोडायचे?" "यासह जोडण्यासाठी:<br><b>%1$s</b><br><br>यावर टाइप करा:<br><b>%2$s</b>, नंतर Return किंवा Enter दाबा." - "%1$s ला आपले संपर्क आणि कॉल इतिहासामध्‍ये प्रवेश करण्‍याची अनुमती द्या" + + "%1$s सह कनेक्ट करणे शक्य झाले नाही." "डिव्हाइसेससाठी स्कॅन करा" @@ -2627,16 +2628,16 @@ "भाषा बदला" "टॅप करा आणि पे करा" "हे कसे कार्य करते" - "दुकानांमध्‍ये आपल्‍या फोनद्वारे देयक द्या" - "देयक डीफॉल्ट" + "दुकानांमध्‍ये आपल्‍या फोनद्वारे पेमेंट द्या" + "पेमेंट डीफॉल्ट" "सेट केले नाही" "%1$s - %2$s" "डीफॉल्ट वापरा" "नेहमी" - "दुसरा देयक अॅप खुला असतो तेव्हा त्यास वगळून" + "दुसरा पेमेंट अॅप खुला असतो तेव्हा त्यास वगळून" "टॅप आणि पे टर्मिनलवर, यासह पे करा:" "टर्मिनलवर देय द्या" - "देयक अॅप सेट करा. त्यानंतर संपर्करहित आयकन असलेल्या कोणत्याही टर्मिनलवर आपल्‍या फोनची मागील बाजू धरा." + "पेमेंट अॅप सेट करा. त्यानंतर संपर्करहित आयकन असलेल्या कोणत्याही टर्मिनलवर आपल्‍या फोनची मागील बाजू धरा." "समजले" "आणखी..." "आपले प्राधान्य म्हणून सेट करायचे?" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 992dad4bdfd..ffa61a256b9 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -25,8 +25,8 @@ "Alternar" "Desconhecido" - Está agora a %1$d passo de se tornar um programador. Está agora a %1$d passos de se tornar um programador. + Está agora a %1$d passo de se tornar um programador. "Agora é um programador!" "Não é necessário, já é um programador." @@ -254,8 +254,8 @@ "Remover" "Adicionar um idioma" - Pretende remover o idioma selecionado? Pretende remover os idiomas selecionados? + Pretende remover o idioma selecionado? "O texto será apresentado noutro idioma." "Não é possível remover todos os idiomas" @@ -359,8 +359,8 @@ "Adicionar impressão digital" "bloqueio de ecrã" - %1$d impressão digital configurada %1$d impressões digitais configuradas + %1$d impressão digital configurada "Desbloq. com impressão digital" @@ -559,28 +559,28 @@ "Tem de incluir, pelo menos, um dígito" "Tem de incluir, pelo menos, um símbolo" - Tem de incluir, pelo menos, 1 letra Tem de incluir, pelo menos, %d letras + Tem de incluir, pelo menos, 1 letra - Tem de incluir, pelo menos, 1 letra minúscula Tem de incluir, pelo menos, %d letras minúsculas + Tem de incluir, pelo menos, 1 letra minúscula - Tem de incluir, pelo menos, 1 letra maiúscula Tem de incluir, pelo menos, %d letras maiúsculas + Tem de incluir, pelo menos, 1 letra maiúscula - Tem de incluir, pelo menos, 1 dígito numérico Tem de incluir, pelo menos, %d dígitos numéricos + Tem de incluir, pelo menos, 1 dígito numérico - Tem de incluir, pelo menos, 1 símbolo especial Tem de incluir, pelo menos, %d símbolos especiais + Tem de incluir, pelo menos, 1 símbolo especial - Tem de incluir, pelo menos, 1 caráter que não seja uma letra Tem de incluir, pelo menos, %d carateres que não sejam letras + Tem de incluir, pelo menos, 1 caráter que não seja uma letra "O admin. do disp. não permite a utilização de uma palavra-passe recente" "Não é permitida uma sequência de dígitos ascendente, descendente ou repetida" @@ -592,15 +592,15 @@ "Aplicações de gestor do dispositivo" "Sem aplicações ativas" - %d aplicação ativa %d aplicações ativas + %d aplicação ativa "Agentes fidedignos" "Para utilizar, defina primeiro um bloqueio de ecrã" "Nenhum" - 1 agente fidedigno ativo %d agentes fidedignos ativos + 1 agente fidedigno ativo "Bluetooth" "Ativar Bluetooth" @@ -618,7 +618,8 @@ "Para sincronizar com: <br><b>%1$s</b><br><br>Verifique se apresenta esta chave de acesso: <br><b>%2$s</b>" "De: <br><b>%1$s</b><br><br> Sincronizar com este aparelho?" "Para sincronizar com:<br><b>%1$s</b><br><br>Introduza no mesmo:<br><b>%2$s</b> e, em seguida, prima Enter." - "Permitir que o dispositivo %1$s aceda aos contactos e ao histórico de chamadas" + + "Não foi possível ligar a %1$s." "Procurar dispositivos" @@ -838,8 +839,8 @@ "Cancelar" "Redes guardadas" - 1 rede %d redes + 1 rede "Wi-Fi Avançada" "Endereço MAC" @@ -1106,8 +1107,8 @@ "O %1$s é o único cartão SIM no dispositivo. Pretende utilizar este cartão SIM para os dados móveis, as chamadas e as mensagens SMS?" "Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo." - Código PIN incorreto. Tem mais %d tentativa antes de ter de contactar operador p/ desbloquear dispos. Código PIN do cartão SIM incorreto. Tem mais %d tentativas. + Código PIN incorreto. Tem mais %d tentativa antes de ter de contactar operador p/ desbloquear dispos. "Falha ao introduzir o PIN do cartão SIM!" "Estado do tablet" @@ -1337,8 +1338,8 @@ "As definições de rede foram repostas" "Repos. dados/fábrica" - 1 conta será reposta %1$d contas serão repostas + 1 conta será reposta "A memória de armazenamento interno e todos os dados serão repostos" "Serão apagados todos os dados do ""armazenamento interno"" do tablet, incluindo:\n\n"
  • "A Conta Google"
  • \n
  • "Dados e definições do sistema e da aplicação"
  • \n
  • "Aplicações transferidas"
  • @@ -1555,8 +1556,8 @@ "Limpar cache" "Cache" - 1 item %d itens + 1 item "Limpar acesso" "Controlos" @@ -1854,24 +1855,24 @@ "Mostrar nas Definições rápidas" "Modo de correção" - Atraso extremamente curto (%1$d ms) Atraso extremamente curto (%1$d ms) + Atraso extremamente curto (%1$d ms) - Atraso muito curto (%1$d ms) Atraso muito curto (%1$d ms) + Atraso muito curto (%1$d ms) - Atraso curto (%1$d ms) Atraso curto (%1$d ms) + Atraso curto (%1$d ms) - Atraso longo (%1$d ms) Atraso longo (%1$d ms) + Atraso longo (%1$d ms) - Atraso muito longo (%1$d ms) Atraso muito longo (%1$d ms) + Atraso muito longo (%1$d ms) "Configurações" "Ativado" @@ -1925,12 +1926,12 @@ "Impressão" "Desativado" - 1 serviço de impressão ativado %1$d serviços de impressão ativados + 1 serviço de impressão ativado - 1 tarefa de impressão %1$d tarefas de impressão + 1 tarefa de impressão "Serviços de impressão" "Nenhum serviço instalado" @@ -2542,21 +2543,21 @@ "A rede pode ser monitorizada" "Concluído" - Confiar ou remover o certificado Confiar ou remover os certificados + Confiar ou remover o certificado - %s instalou uma autoridade de certificação no seu dispositivo que pode permitir monitorizar a atividade na rede do dispositivo, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca deste certificado, contacte o gestor. %s instalou autoridades de certificação no seu dispositivo que podem permitir monitorizar a atividade na rede do dispositivo, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca destes certificados, contacte o gestor. + %s instalou uma autoridade de certificação no seu dispositivo que pode permitir monitorizar a atividade na rede do dispositivo, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca deste certificado, contacte o gestor. - %s instalou uma autoridade de certificação para o seu perfil de trabalho que pode permitir monitorizar a atividade na rede de trabalho, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca deste certificado, contacte o gestor. %s instalou autoridades de certificação para o seu perfil de trabalho que podem permitir monitorizar a atividade na rede de trabalho, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca destes certificados, contacte o gestor. + %s instalou uma autoridade de certificação para o seu perfil de trabalho que pode permitir monitorizar a atividade na rede de trabalho, incluindo emails, aplicações e Websites seguros.\n\nPara obter mais informações acerca deste certificado, contacte o gestor. "A sua atividade de rede, incluindo emails, aplicações e Sites seguros, pode ser monitorizada por terceiros.\n\nIsto é possível através de uma credencial fidedigna instalada no seu dispositivo." - Verificar certificado Verificar certificados + Verificar certificado "Utilizadores" "Utilizadores e perfis" @@ -2733,8 +2734,8 @@ "A seleção é necessária" "Definições" - Mostrar %d item oculto Mostrar %d itens ocultos + Mostrar %d item oculto "Rede e Internet" "rede móvel" @@ -2835,8 +2836,8 @@ "Ativar sons" "Nenhuma regra automática ativada" - 1 regra automática ativada %d regras automáticas ativadas + 1 regra automática ativada "Preferências de Não incomodar" "Prioridade permite apenas" @@ -2903,8 +2904,8 @@ "O acesso às notificações do perfil de trabalho está bloqueado" "As aplicações não podem ler notificações" - %d aplicação pode ler notificações %d aplicações podem ler notificações + %d aplicação pode ler notificações "Nenhuma aplicação instalada solicitou acesso a notificações" "Pretende permitir o acesso a notificações de %1$s?" @@ -2936,12 +2937,12 @@ "Definições adicionais na aplicação" "Ativadas para todas as aplicações" - Desativado para %d aplicação Desativado para %d aplicações + Desativado para %d aplicação - %d categoria eliminada %d categorias eliminadas + %d categoria eliminada "Ativadas" "Desativadas" @@ -3024,12 +3025,12 @@ "%s do dia seguinte" "Alterar para alarmes apenas, indefinidamente" - Alterar para alarmes apenas durante um minuto até à(s) %2$s Alterar para alarmes apenas durante %1$d minutos (até à(s) %2$s) + Alterar para alarmes apenas durante um minuto até à(s) %2$s - Alterar para alarmes apenas durante uma hora até à(s) %2$s Alterar para alarmes apenas durante %1$d horas até à(s) %2$s + Alterar para alarmes apenas durante uma hora até à(s) %2$s "Alterar para alarmes apenas, até %1$s" "Alterar para interromper sempre" @@ -3102,16 +3103,16 @@ "Nível %d" "%1$s%2$s" - %d autorização concedida %d autorizações concedidas + %d autorização concedida - %d de %d autorização concedida %d de %d autorizações concedidas + %d de %d autorização concedida - %d permissão adicional %d permissões adicionais + %d permissão adicional "Nenhuma permissão concedida" "Nenhuma permissão solicitada" @@ -3139,8 +3140,8 @@ "Abrir %s e outros URLs" "Nenhum aplicação abre links compatíveis" - Uma aplicação que abre links compatíveis %d aplicações que abrem links compatíveis + Uma aplicação que abre links compatíveis "Abrir com esta aplicação" "Perguntar sempre" @@ -3183,12 +3184,12 @@ "Mostrar utilização de aplic." "Utilização elevada" - %1$s aplicação está a apresentar um comportamento anormal %2$d aplicações estão a apresentar um comportamento anormal + %1$s aplicação está a apresentar um comportamento anormal - %1$s a consumir rapidamente a bateria Aplicações a consumir rapidamente a bateria + %1$s a consumir rapidamente a bateria "Não otimizada" "Não otimizada" @@ -3251,8 +3252,8 @@ "Disponível" "Memória utilizada pelas aplicações" - 1 aplicação utilizou a memória nos(as) últimos(as) %2$s %1$d aplicações utilizaram a memória nos(as) últimos(as) %2$s + 1 aplicação utilizou a memória nos(as) últimos(as) %2$s "Frequência" "Utilização máxima" @@ -3322,8 +3323,8 @@ "Sem ligação" "%1$s dos dados utilizados" - Desativadas para 1 aplicação Desativadas para %d aplicações + Desativadas para 1 aplicação "Ativadas para todas as aplicações" "%1$d aplicações instaladas" @@ -3375,12 +3376,12 @@ "+%1$d" "Mais %1$d" - 1 sugestão %1$d sugestões + 1 sugestão - Mais 1 sugestão Mais %1$d sugestões + Mais 1 sugestão "Remover" "Temperatura da cor fria" @@ -3403,8 +3404,8 @@ "Mensalmente no dia %1$s" "Restrições de rede" - 1 restrição %1$d restrições + 1 restrição "A contagem de dados do operador pode ser diferente da contagem do dispositivo" "%1$s utilizado(s)" @@ -3416,8 +3417,8 @@ "Configurar" "Outras aplicações incluídas na utilização" - 1 aplicação autorizada a utilizar dados sem restrições quando a Poupança de dados está ativada %1$d aplicações autorizadas a utilizar dados sem restrições quando a Poupança de dados está ativada + 1 aplicação autorizada a utilizar dados sem restrições quando a Poupança de dados está ativada "Poupança de dados" "Dados sem restrições" @@ -3474,8 +3475,8 @@ "O objeto de classificação não contém esta chave." "Acesso especial a aplicações" - 1 aplicação pode utilizar dados sem restrições %d aplicações podem utilizar dados sem restrições + 1 aplicação pode utilizar dados sem restrições "Pretende mesmo limpar os dados do utilizador e converter para a encriptação de ficheiros?" "Limpar e converter" @@ -3523,16 +3524,16 @@ "Pesquisa de contactos" "Permitir pesquisa de contactos por parte da sua entidade para identificar autores das chamadas e contactos" - 1 hora %s horas + 1 hora - 1 minuto %s minutos + 1 minuto - 1 segundo %s segundos + 1 segundo "Tempo de espera de ~%1$s" "Computador" @@ -3621,16 +3622,16 @@ "Aplicações instaladas" "O número de aplicações é uma estimativa. Pode não incluir as aplicações instaladas fora da Play Store." - No mínimo, %d aplicação No mínimo, %d aplicações + No mínimo, %d aplicação "Autorizações de acesso à localização" "Autorizações do microfone" "Autorizações da câmara" "Aplicações predefinidas" - %d aplicação %d aplicações + %d aplicação "Teclado predefinido" "Definido como %s" @@ -3640,35 +3641,35 @@ "Proxy HTTP global definido" "Credenciais fidedignas" - No mínimo, %d certificado da AC No mínimo, %d certificados da AC + No mínimo, %d certificado da AC "O gestor pode bloquear o dispositivo e repor a palavra-passe" "O gestor pode eliminar todos os dados do dispositivo" "Tentativas de introdução da palavra-passe falhadas antes da eliminação de todos os dados do dispositivo" "Tentativas de introdução da palavra-passe falhadas antes da eliminação de todos os dados do perfil de trabalho" - %d tentativa %d tentativas + %d tentativa "Este dispositivo é gerido pela sua entidade." "Este dispositivo é gerido por %s." " " "Saiba mais" - Aplicação de câmara Aplicações de câmara + Aplicação de câmara "Aplicação de calendário" "Aplicação de contactos" - Aplicação de cliente de email Aplicações de cliente de email + Aplicação de cliente de email "Aplicação de mapas" - Aplicação de telefone Aplicações de telefone + Aplicação de telefone "%1$s, %2$s" "%1$s, %2$s, %3$s" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 6efd49ed1fd..0e83e8b0786 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -640,7 +640,8 @@ "Щоб створити пару з пристроєм:<br><b>%1$s</b><br><br>Переконайтеся, що відображається цей ключ доступу:<br><b>%2$s</b>" "Від пристрою:<br><b>%1$s</b><br><br>Створити пару з цим пристроєм?" "Щоб створити пару з пристроєм: <br><b>%1$s</b><br><br> Введіть на ньому: <br><b>%2$s</b>, а потім натисніть \"Повернутися\" або \"Ввійти\"." - "Надати пристрою %1$s доступ до контактів та історії дзвінків" + + "Не вдалося з’єднатися з пристроєм %1$s." "Сканув. пристроїв" @@ -3225,7 +3226,7 @@ "Помічник і голосовий ввід" "Додаток-помічник" "Зробити додаток %s помічником?" - "Помічник матиме доступ до інформації про додатки у вашій системі, зокрема до даних на екрані та в додатках." + "Асистент матиме доступ до інформації про додатки у вашій системі, зокрема до даних на екрані та в додатках." "Прийняти" "Не приймати" "Вибрати голосовий ввід" From 1240549591b9319022ec36f6b51b7c885482d88a Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 5 Dec 2017 13:03:29 -0800 Subject: [PATCH 11/13] Move AppListGroup to PreferenceController Move the app list in battery settings to PreferenceController. So that we can: 1. Clean the code in PowerUsageSummary 2. Make it easy to add/move the app list to other place in furture. This cl: 1. Move and make it invisible since in P we don't show app list in battery main page. 2. Move related test to BatteryAppListPreferenceControllerTest Bug: 70234293 Test: RunSettingsRoboTests Change-Id: Ice7a42394916ff5e71305bfe22f5c35868d87fc7 --- res/color/battery_icon_color_error.xml | 2 +- .../BatteryAppListPreferenceController.java | 482 ++++++++++++++++++ .../settings/fuelgauge/PowerUsageSummary.java | 369 +------------- ...atteryAppListPreferenceControllerTest.java | 204 ++++++++ .../fuelgauge/PowerUsageSummaryTest.java | 422 +++++++++++++++ 5 files changed, 1125 insertions(+), 354 deletions(-) create mode 100644 src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java diff --git a/res/color/battery_icon_color_error.xml b/res/color/battery_icon_color_error.xml index 3a71aaef891..99c7d7d9dac 100644 --- a/res/color/battery_icon_color_error.xml +++ b/res/color/battery_icon_color_error.xml @@ -14,6 +14,6 @@ limitations under the License. --> - \ No newline at end of file diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java new file mode 100644 index 00000000000..ee0ed212f99 --- /dev/null +++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java @@ -0,0 +1,482 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + */ + +package com.android.settings.fuelgauge; + +import android.app.Activity; +import android.app.Fragment; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.BatteryStats; +import android.os.Handler; +import android.os.Message; +import android.os.Process; +import android.os.UserHandle; +import android.os.UserManager; +import android.support.annotation.VisibleForTesting; +import android.support.v14.preference.PreferenceFragment; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceGroup; +import android.support.v7.preference.PreferenceManager; +import android.support.v7.preference.PreferenceScreen; +import android.text.TextUtils; +import android.text.format.DateUtils; +import android.util.ArrayMap; +import android.util.Log; +import android.util.SparseArray; + +import com.android.internal.os.BatterySipper; +import com.android.internal.os.BatterySipper.DrainType; +import com.android.internal.os.BatteryStatsHelper; +import com.android.internal.os.PowerProfile; +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settings.Utils; +import com.android.settings.core.instrumentation.MetricsFeatureProvider; +import com.android.settings.fuelgauge.anomaly.Anomaly; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnDestroy; +import com.android.settingslib.core.lifecycle.events.OnPause; + +import java.util.ArrayList; +import java.util.List; + +/** + * Controller that update the battery header view + */ +public class BatteryAppListPreferenceController extends AbstractPreferenceController + implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy { + private static final boolean USE_FAKE_DATA = true; + private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10; + private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10; + private static final int STATS_TYPE = BatteryStats.STATS_SINCE_CHARGED; + + private final String mPreferenceKey; + @VisibleForTesting + PreferenceGroup mAppListGroup; + private BatteryStatsHelper mBatteryStatsHelper; + private ArrayMap mPreferenceCache; + @VisibleForTesting + BatteryUtils mBatteryUtils; + private UserManager mUserManager; + private SettingsActivity mActivity; + private PreferenceFragment mFragment; + private Context mPrefContext; + SparseArray> mAnomalySparseArray; + + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case BatteryEntry.MSG_UPDATE_NAME_ICON: + BatteryEntry entry = (BatteryEntry) msg.obj; + PowerGaugePreference pgp = + (PowerGaugePreference) mAppListGroup.findPreference( + Integer.toString(entry.sipper.uidObj.getUid())); + if (pgp != null) { + final int userId = UserHandle.getUserId(entry.sipper.getUid()); + final UserHandle userHandle = new UserHandle(userId); + pgp.setIcon(mUserManager.getBadgedIconForUser(entry.getIcon(), userHandle)); + pgp.setTitle(entry.name); + if (entry.sipper.drainType == DrainType.APP) { + pgp.setContentDescription(entry.name); + } + } + break; + case BatteryEntry.MSG_REPORT_FULLY_DRAWN: + Activity activity = mActivity; + if (activity != null) { + activity.reportFullyDrawn(); + } + break; + } + super.handleMessage(msg); + } + }; + + public BatteryAppListPreferenceController(Context context, String preferenceKey, + Lifecycle lifecycle, SettingsActivity activity, PreferenceFragment fragment) { + super(context); + + if (lifecycle != null) { + lifecycle.addObserver(this); + } + + mPreferenceKey = preferenceKey; + mBatteryUtils = BatteryUtils.getInstance(context); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mActivity = activity; + mFragment = fragment; + } + + @Override + public void onPause() { + BatteryEntry.stopRequestQueue(); + mHandler.removeMessages(BatteryEntry.MSG_UPDATE_NAME_ICON); + } + + @Override + public void onDestroy() { + if (mActivity.isChangingConfigurations()) { + BatteryEntry.clearUidCache(); + } + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPrefContext = screen.getContext(); + mAppListGroup = (PreferenceGroup) screen.findPreference(mPreferenceKey); + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public String getPreferenceKey() { + return mPreferenceKey; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (preference instanceof PowerGaugePreference) { + PowerGaugePreference pgp = (PowerGaugePreference) preference; + BatteryEntry entry = pgp.getInfo(); + AdvancedPowerUsageDetail.startBatteryDetailPage(mActivity, + mFragment, mBatteryStatsHelper, STATS_TYPE, entry, pgp.getPercent(), + mAnomalySparseArray != null ? mAnomalySparseArray.get(entry.sipper.getUid()) + : null); + return true; + } + return false; + } + + public void refreshAnomalyIcon(final SparseArray> anomalySparseArray) { + if (!isAvailable()) { + return; + } + mAnomalySparseArray = anomalySparseArray; + for (int i = 0, size = anomalySparseArray.size(); i < size; i++) { + final String key = extractKeyFromUid(anomalySparseArray.keyAt(i)); + final PowerGaugePreference pref = (PowerGaugePreference) mAppListGroup.findPreference( + key); + if (pref != null) { + pref.shouldShowAnomalyIcon(true); + } + } + } + + public void refreshAppListGroup(BatteryStatsHelper statsHelper, boolean showAllApps, + CharSequence timeSequence) { + if (!isAvailable()) { + return; + } + mBatteryStatsHelper = statsHelper; + final int resId = showAllApps ? R.string.power_usage_list_summary_device + : R.string.power_usage_list_summary; + mAppListGroup.setTitle(TextUtils.expandTemplate(mContext.getText(resId), timeSequence)); + + final PowerProfile powerProfile = statsHelper.getPowerProfile(); + final BatteryStats stats = statsHelper.getStats(); + final double averagePower = powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL); + boolean addedSome = false; + final int dischargeAmount = USE_FAKE_DATA ? 5000 + : stats != null ? stats.getDischargeAmount(STATS_TYPE) : 0; + + cacheRemoveAllPrefs(mAppListGroup); + mAppListGroup.setOrderingAsAdded(false); + + if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP || USE_FAKE_DATA) { + final List usageList = getCoalescedUsageList( + USE_FAKE_DATA ? getFakeStats() : statsHelper.getUsageList()); + double hiddenPowerMah = showAllApps ? 0 : + mBatteryUtils.removeHiddenBatterySippers(usageList); + mBatteryUtils.sortUsageList(usageList); + + final int numSippers = usageList.size(); + for (int i = 0; i < numSippers; i++) { + final BatterySipper sipper = usageList.get(i); + double totalPower = USE_FAKE_DATA ? 4000 : statsHelper.getTotalPower(); + + final double percentOfTotal = mBatteryUtils.calculateBatteryPercent( + sipper.totalPowerMah, totalPower, hiddenPowerMah, dischargeAmount); + + if (((int) (percentOfTotal + .5)) < 1) { + continue; + } + if (shouldHideSipper(sipper)) { + continue; + } + final UserHandle userHandle = new UserHandle(UserHandle.getUserId(sipper.getUid())); + final BatteryEntry entry = new BatteryEntry(mActivity, mHandler, mUserManager, + sipper); + final Drawable badgedIcon = mUserManager.getBadgedIconForUser(entry.getIcon(), + userHandle); + final CharSequence contentDescription = mUserManager.getBadgedLabelForUser( + entry.getLabel(), + userHandle); + + final String key = extractKeyFromSipper(sipper); + PowerGaugePreference pref = (PowerGaugePreference) getCachedPreference(key); + if (pref == null) { + pref = new PowerGaugePreference(mPrefContext, badgedIcon, + contentDescription, entry); + pref.setKey(key); + } + sipper.percent = percentOfTotal; + pref.setTitle(entry.getLabel()); + pref.setOrder(i + 1); + pref.setPercent(percentOfTotal); + pref.shouldShowAnomalyIcon(false); + if (sipper.usageTimeMs == 0 && sipper.drainType == DrainType.APP) { + sipper.usageTimeMs = mBatteryUtils.getProcessTimeMs( + BatteryUtils.StatusType.FOREGROUND, sipper.uidObj, STATS_TYPE); + } + setUsageSummary(pref, sipper); + addedSome = true; + mAppListGroup.addPreference(pref); + if (mAppListGroup.getPreferenceCount() - getCachedCount() + > (MAX_ITEMS_TO_LIST + 1)) { + break; + } + } + } + if (!addedSome) { + addNotAvailableMessage(); + } + removeCachedPrefs(mAppListGroup); + + BatteryEntry.startRequestQueue(); + } + + /** + * We want to coalesce some UIDs. For example, dex2oat runs under a shared gid that + * exists for all users of the same app. We detect this case and merge the power use + * for dex2oat to the device OWNER's use of the app. + * + * @return A sorted list of apps using power. + */ + private List getCoalescedUsageList(final List sippers) { + final SparseArray uidList = new SparseArray<>(); + + final ArrayList results = new ArrayList<>(); + final int numSippers = sippers.size(); + for (int i = 0; i < numSippers; i++) { + BatterySipper sipper = sippers.get(i); + if (sipper.getUid() > 0) { + int realUid = sipper.getUid(); + + // Check if this UID is a shared GID. If so, we combine it with the OWNER's + // actual app UID. + if (isSharedGid(sipper.getUid())) { + realUid = UserHandle.getUid(UserHandle.USER_SYSTEM, + UserHandle.getAppIdFromSharedAppGid(sipper.getUid())); + } + + // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc). + if (isSystemUid(realUid) + && !"mediaserver".equals(sipper.packageWithHighestDrain)) { + // Use the system UID for all UIDs running in their own sandbox that + // are not apps. We exclude mediaserver because we already are expected to + // report that as a separate item. + realUid = Process.SYSTEM_UID; + } + + if (realUid != sipper.getUid()) { + // Replace the BatterySipper with a new one with the real UID set. + BatterySipper newSipper = new BatterySipper(sipper.drainType, + new FakeUid(realUid), 0.0); + newSipper.add(sipper); + newSipper.packageWithHighestDrain = sipper.packageWithHighestDrain; + newSipper.mPackages = sipper.mPackages; + sipper = newSipper; + } + + int index = uidList.indexOfKey(realUid); + if (index < 0) { + // New entry. + uidList.put(realUid, sipper); + } else { + // Combine BatterySippers if we already have one with this UID. + final BatterySipper existingSipper = uidList.valueAt(index); + existingSipper.add(sipper); + if (existingSipper.packageWithHighestDrain == null + && sipper.packageWithHighestDrain != null) { + existingSipper.packageWithHighestDrain = sipper.packageWithHighestDrain; + } + + final int existingPackageLen = existingSipper.mPackages != null ? + existingSipper.mPackages.length : 0; + final int newPackageLen = sipper.mPackages != null ? + sipper.mPackages.length : 0; + if (newPackageLen > 0) { + String[] newPackages = new String[existingPackageLen + newPackageLen]; + if (existingPackageLen > 0) { + System.arraycopy(existingSipper.mPackages, 0, newPackages, 0, + existingPackageLen); + } + System.arraycopy(sipper.mPackages, 0, newPackages, existingPackageLen, + newPackageLen); + existingSipper.mPackages = newPackages; + } + } + } else { + results.add(sipper); + } + } + + final int numUidSippers = uidList.size(); + for (int i = 0; i < numUidSippers; i++) { + results.add(uidList.valueAt(i)); + } + + // The sort order must have changed, so re-sort based on total power use. + mBatteryUtils.sortUsageList(results); + return results; + } + + @VisibleForTesting + void setUsageSummary(Preference preference, BatterySipper sipper) { + // Only show summary when usage time is longer than one minute + final long usageTimeMs = sipper.usageTimeMs; + if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) { + final CharSequence timeSequence = Utils.formatElapsedTime(mContext, usageTimeMs, + false); + preference.setSummary( + (sipper.drainType != DrainType.APP || mBatteryUtils.shouldHideSipper(sipper)) + ? timeSequence + : TextUtils.expandTemplate(mContext.getText(R.string.battery_used_for), + timeSequence)); + } + } + + @VisibleForTesting + boolean shouldHideSipper(BatterySipper sipper) { + // Don't show over-counted and unaccounted in any condition + return sipper.drainType == BatterySipper.DrainType.OVERCOUNTED + || sipper.drainType == BatterySipper.DrainType.UNACCOUNTED; + } + + @VisibleForTesting + String extractKeyFromSipper(BatterySipper sipper) { + if (sipper.uidObj != null) { + return extractKeyFromUid(sipper.getUid()); + } else if (sipper.drainType == DrainType.USER) { + return sipper.drainType.toString() + sipper.userId; + } else if (sipper.drainType != DrainType.APP) { + return sipper.drainType.toString(); + } else if (sipper.getPackages() != null) { + return TextUtils.concat(sipper.getPackages()).toString(); + } else { + Log.w(TAG, "Inappropriate BatterySipper without uid and package names: " + sipper); + return "-1"; + } + } + + @VisibleForTesting + String extractKeyFromUid(int uid) { + return Integer.toString(uid); + } + + private void cacheRemoveAllPrefs(PreferenceGroup group) { + mPreferenceCache = new ArrayMap<>(); + final int N = group.getPreferenceCount(); + for (int i = 0; i < N; i++) { + Preference p = group.getPreference(i); + if (TextUtils.isEmpty(p.getKey())) { + continue; + } + mPreferenceCache.put(p.getKey(), p); + } + } + + private static boolean isSharedGid(int uid) { + return UserHandle.getAppIdFromSharedAppGid(uid) > 0; + } + + private static boolean isSystemUid(int uid) { + final int appUid = UserHandle.getAppId(uid); + return appUid >= Process.SYSTEM_UID && appUid < Process.FIRST_APPLICATION_UID; + } + + private static List getFakeStats() { + ArrayList stats = new ArrayList<>(); + float use = 5; + for (DrainType type : DrainType.values()) { + if (type == DrainType.APP) { + continue; + } + stats.add(new BatterySipper(type, null, use)); + use += 5; + } + for (int i = 0; i < 100; i++) { + stats.add(new BatterySipper(DrainType.APP, + new FakeUid(Process.FIRST_APPLICATION_UID + i), use)); + } + stats.add(new BatterySipper(DrainType.APP, + new FakeUid(0), use)); + + // Simulate dex2oat process. + BatterySipper sipper = new BatterySipper(DrainType.APP, + new FakeUid(UserHandle.getSharedAppGid(Process.FIRST_APPLICATION_UID)), 10.0f); + sipper.packageWithHighestDrain = "dex2oat"; + stats.add(sipper); + + sipper = new BatterySipper(DrainType.APP, + new FakeUid(UserHandle.getSharedAppGid(Process.FIRST_APPLICATION_UID + 1)), 10.0f); + sipper.packageWithHighestDrain = "dex2oat"; + stats.add(sipper); + + sipper = new BatterySipper(DrainType.APP, + new FakeUid(UserHandle.getSharedAppGid(Process.LOG_UID)), 9.0f); + stats.add(sipper); + + return stats; + } + + private Preference getCachedPreference(String key) { + return mPreferenceCache != null ? mPreferenceCache.remove(key) : null; + } + + private void removeCachedPrefs(PreferenceGroup group) { + for (Preference p : mPreferenceCache.values()) { + group.removePreference(p); + } + mPreferenceCache = null; + } + + private int getCachedCount() { + return mPreferenceCache != null ? mPreferenceCache.size() : 0; + } + + private void addNotAvailableMessage() { + final String NOT_AVAILABLE = "not_available"; + Preference notAvailable = getCachedPreference(NOT_AVAILABLE); + if (notAvailable == null) { + notAvailable = new Preference(mPrefContext); + notAvailable.setKey(NOT_AVAILABLE); + notAvailable.setTitle(R.string.power_usage_not_available); + mAppListGroup.addPreference(notAvailable); + } + } +} diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index ed5b6f40cfc..e4b70a14372 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -21,21 +21,13 @@ import android.app.LoaderManager; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.Loader; -import android.graphics.drawable.Drawable; import android.os.BatteryStats; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Process; -import android.os.UserHandle; import android.provider.SearchIndexableResource; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceGroup; -import android.text.TextUtils; -import android.text.format.DateUtils; import android.text.format.Formatter; -import android.util.Log; import android.util.SparseArray; import android.view.Menu; import android.view.MenuInflater; @@ -49,7 +41,6 @@ import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatterySipper.DrainType; -import com.android.internal.os.PowerProfile; import com.android.settings.R; import com.android.settings.Settings.HighPowerApplicationsActivity; import com.android.settings.SettingsActivity; @@ -71,6 +62,7 @@ import com.android.settings.fuelgauge.anomaly.AnomalyUtils; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; import java.util.ArrayList; import java.util.Arrays; @@ -86,12 +78,9 @@ public class PowerUsageSummary extends PowerUsageBase implements static final String TAG = "PowerUsageSummary"; private static final boolean DEBUG = false; - private static final boolean USE_FAKE_DATA = false; private static final String KEY_APP_LIST = "app_list"; private static final String KEY_BATTERY_HEADER = "battery_header"; private static final String KEY_SHOW_ALL_APPS = "show_all_apps"; - private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10; - private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10; private static final String KEY_SCREEN_USAGE = "screen_usage"; private static final String KEY_TIME_SINCE_LAST_FULL_CHARGE = "last_full_charge"; @@ -136,6 +125,7 @@ public class PowerUsageSummary extends PowerUsageBase implements PreferenceGroup mAppListGroup; @VisibleForTesting BatteryHeaderPreferenceController mBatteryHeaderPreferenceController; + private BatteryAppListPreferenceController mBatteryAppListPreferenceController; private AnomalySummaryPreferenceController mAnomalySummaryPreferenceController; private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; @@ -157,7 +147,7 @@ public class PowerUsageSummary extends PowerUsageBase implements mAnomalySummaryPreferenceController.updateAnomalySummaryPreference(data); updateAnomalySparseArray(data); - refreshAnomalyIcon(); + mBatteryAppListPreferenceController.refreshAnomalyIcon(mAnomalySparseArray); } @Override @@ -235,7 +225,6 @@ public class PowerUsageSummary extends PowerUsageBase implements initFeatureProvider(); mBatteryLayoutPref = (LayoutPreference) findPreference(KEY_BATTERY_HEADER); - mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST); mScreenUsagePref = (PowerGaugePreference) findPreference(KEY_SCREEN_USAGE); mLastFullChargePref = (PowerGaugePreference) findPreference( KEY_TIME_SINCE_LAST_FULL_CHARGE); @@ -254,21 +243,6 @@ public class PowerUsageSummary extends PowerUsageBase implements return MetricsEvent.FUELGAUGE_POWER_USAGE_SUMMARY_V2; } - @Override - public void onPause() { - BatteryEntry.stopRequestQueue(); - mHandler.removeMessages(BatteryEntry.MSG_UPDATE_NAME_ICON); - super.onPause(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - if (getActivity().isChangingConfigurations()) { - BatteryEntry.clearUidCache(); - } - } - @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -283,14 +257,7 @@ public class PowerUsageSummary extends PowerUsageBase implements if (KEY_BATTERY_HEADER.equals(preference.getKey())) { performBatteryHeaderClick(); return true; - } else if (!(preference instanceof PowerGaugePreference)) { - return super.onPreferenceTreeClick(preference); } - PowerGaugePreference pgp = (PowerGaugePreference) preference; - BatteryEntry entry = pgp.getInfo(); - AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), - this, mStatsHelper, mStatsType, entry, pgp.getPercent(), - mAnomalySparseArray.get(entry.sipper.getUid())); return super.onPreferenceTreeClick(preference); } @@ -306,10 +273,15 @@ public class PowerUsageSummary extends PowerUsageBase implements @Override protected List getPreferenceControllers(Context context) { + final Lifecycle lifecycle = getLifecycle(); + final SettingsActivity activity = (SettingsActivity) getActivity(); final List controllers = new ArrayList<>(); mBatteryHeaderPreferenceController = new BatteryHeaderPreferenceController( - context, getActivity(), this /* host */, getLifecycle()); + context, activity, this /* host */, getLifecycle()); controllers.add(mBatteryHeaderPreferenceController); + mBatteryAppListPreferenceController = new BatteryAppListPreferenceController(context, + KEY_APP_LIST, lifecycle, activity, this); + controllers.add(mBatteryAppListPreferenceController); controllers.add(new AutoBrightnessPreferenceController(context, KEY_AUTO_BRIGHTNESS)); controllers.add(new TimeoutPreferenceController(context, KEY_SCREEN_TIMEOUT)); controllers.add(new BatterySaverController(context, getLifecycle())); @@ -388,17 +360,6 @@ public class PowerUsageSummary extends PowerUsageBase implements } } - private void addNotAvailableMessage() { - final String NOT_AVAILABLE = "not_available"; - Preference notAvailable = getCachedPreference(NOT_AVAILABLE); - if (notAvailable == null) { - notAvailable = new Preference(getPrefContext()); - notAvailable.setKey(NOT_AVAILABLE); - notAvailable.setTitle(R.string.power_usage_not_available); - mAppListGroup.addPreference(notAvailable); - } - } - private void performBatteryHeaderClick() { if (mPowerFeatureProvider.isAdvancedUiEnabled()) { Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null, @@ -415,101 +376,6 @@ public class PowerUsageSummary extends PowerUsageBase implements } } - private static boolean isSharedGid(int uid) { - return UserHandle.getAppIdFromSharedAppGid(uid) > 0; - } - - private static boolean isSystemUid(int uid) { - final int appUid = UserHandle.getAppId(uid); - return appUid >= Process.SYSTEM_UID && appUid < Process.FIRST_APPLICATION_UID; - } - - /** - * We want to coalesce some UIDs. For example, dex2oat runs under a shared gid that - * exists for all users of the same app. We detect this case and merge the power use - * for dex2oat to the device OWNER's use of the app. - * - * @return A sorted list of apps using power. - */ - private List getCoalescedUsageList(final List sippers) { - final SparseArray uidList = new SparseArray<>(); - - final ArrayList results = new ArrayList<>(); - final int numSippers = sippers.size(); - for (int i = 0; i < numSippers; i++) { - BatterySipper sipper = sippers.get(i); - if (sipper.getUid() > 0) { - int realUid = sipper.getUid(); - - // Check if this UID is a shared GID. If so, we combine it with the OWNER's - // actual app UID. - if (isSharedGid(sipper.getUid())) { - realUid = UserHandle.getUid(UserHandle.USER_SYSTEM, - UserHandle.getAppIdFromSharedAppGid(sipper.getUid())); - } - - // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc). - if (isSystemUid(realUid) - && !"mediaserver".equals(sipper.packageWithHighestDrain)) { - // Use the system UID for all UIDs running in their own sandbox that - // are not apps. We exclude mediaserver because we already are expected to - // report that as a separate item. - realUid = Process.SYSTEM_UID; - } - - if (realUid != sipper.getUid()) { - // Replace the BatterySipper with a new one with the real UID set. - BatterySipper newSipper = new BatterySipper(sipper.drainType, - new FakeUid(realUid), 0.0); - newSipper.add(sipper); - newSipper.packageWithHighestDrain = sipper.packageWithHighestDrain; - newSipper.mPackages = sipper.mPackages; - sipper = newSipper; - } - - int index = uidList.indexOfKey(realUid); - if (index < 0) { - // New entry. - uidList.put(realUid, sipper); - } else { - // Combine BatterySippers if we already have one with this UID. - final BatterySipper existingSipper = uidList.valueAt(index); - existingSipper.add(sipper); - if (existingSipper.packageWithHighestDrain == null - && sipper.packageWithHighestDrain != null) { - existingSipper.packageWithHighestDrain = sipper.packageWithHighestDrain; - } - - final int existingPackageLen = existingSipper.mPackages != null ? - existingSipper.mPackages.length : 0; - final int newPackageLen = sipper.mPackages != null ? - sipper.mPackages.length : 0; - if (newPackageLen > 0) { - String[] newPackages = new String[existingPackageLen + newPackageLen]; - if (existingPackageLen > 0) { - System.arraycopy(existingSipper.mPackages, 0, newPackages, 0, - existingPackageLen); - } - System.arraycopy(sipper.mPackages, 0, newPackages, existingPackageLen, - newPackageLen); - existingSipper.mPackages = newPackages; - } - } - } else { - results.add(sipper); - } - } - - final int numUidSippers = uidList.size(); - for (int i = 0; i < numUidSippers; i++) { - results.add(uidList.valueAt(i)); - } - - // The sort order must have changed, so re-sort based on total power use. - mBatteryUtils.sortUsageList(results); - return results; - } - protected void refreshUi() { final Context context = getContext(); if (context == null) { @@ -527,102 +393,8 @@ public class PowerUsageSummary extends PowerUsageBase implements final CharSequence timeSequence = Utils.formatRelativeTime(context, lastFullChargeTime, false); - final int resId = mShowAllApps ? R.string.power_usage_list_summary_device - : R.string.power_usage_list_summary; - mAppListGroup.setTitle(TextUtils.expandTemplate(getText(resId), timeSequence)); - - refreshAppListGroup(); - } - - private void refreshAppListGroup() { - final PowerProfile powerProfile = mStatsHelper.getPowerProfile(); - final BatteryStats stats = mStatsHelper.getStats(); - final double averagePower = powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL); - boolean addedSome = false; - final int dischargeAmount = USE_FAKE_DATA ? 5000 - : stats != null ? stats.getDischargeAmount(mStatsType) : 0; - - cacheRemoveAllPrefs(mAppListGroup); - mAppListGroup.setOrderingAsAdded(false); - - if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP || USE_FAKE_DATA) { - final List usageList = getCoalescedUsageList( - USE_FAKE_DATA ? getFakeStats() : mStatsHelper.getUsageList()); - double hiddenPowerMah = mShowAllApps ? 0 : - mBatteryUtils.removeHiddenBatterySippers(usageList); - mBatteryUtils.sortUsageList(usageList); - - final int numSippers = usageList.size(); - for (int i = 0; i < numSippers; i++) { - final BatterySipper sipper = usageList.get(i); - double totalPower = USE_FAKE_DATA ? 4000 : mStatsHelper.getTotalPower(); - - final double percentOfTotal = mBatteryUtils.calculateBatteryPercent( - sipper.totalPowerMah, totalPower, hiddenPowerMah, dischargeAmount); - - if (((int) (percentOfTotal + .5)) < 1) { - continue; - } - if (shouldHideSipper(sipper)) { - continue; - } - final UserHandle userHandle = new UserHandle(UserHandle.getUserId(sipper.getUid())); - final BatteryEntry entry = new BatteryEntry(getActivity(), mHandler, mUm, sipper); - final Drawable badgedIcon = mUm.getBadgedIconForUser(entry.getIcon(), - userHandle); - final CharSequence contentDescription = mUm.getBadgedLabelForUser(entry.getLabel(), - userHandle); - - final String key = extractKeyFromSipper(sipper); - PowerGaugePreference pref = (PowerGaugePreference) getCachedPreference(key); - if (pref == null) { - pref = new PowerGaugePreference(getPrefContext(), badgedIcon, - contentDescription, entry); - pref.setKey(key); - } - sipper.percent = percentOfTotal; - pref.setTitle(entry.getLabel()); - pref.setOrder(i + 1); - pref.setPercent(percentOfTotal); - pref.shouldShowAnomalyIcon(false); - if (sipper.usageTimeMs == 0 && sipper.drainType == DrainType.APP) { - sipper.usageTimeMs = mBatteryUtils.getProcessTimeMs( - BatteryUtils.StatusType.FOREGROUND, sipper.uidObj, mStatsType); - } - setUsageSummary(pref, sipper); - addedSome = true; - mAppListGroup.addPreference(pref); - if (mAppListGroup.getPreferenceCount() - getCachedCount() - > (MAX_ITEMS_TO_LIST + 1)) { - break; - } - } - } - if (!addedSome) { - addNotAvailableMessage(); - } - removeCachedPrefs(mAppListGroup); - - BatteryEntry.startRequestQueue(); - } - - @VisibleForTesting - boolean shouldHideSipper(BatterySipper sipper) { - // Don't show over-counted and unaccounted in any condition - return sipper.drainType == BatterySipper.DrainType.OVERCOUNTED - || sipper.drainType == BatterySipper.DrainType.UNACCOUNTED; - } - - @VisibleForTesting - void refreshAnomalyIcon() { - for (int i = 0, size = mAnomalySparseArray.size(); i < size; i++) { - final String key = extractKeyFromUid(mAnomalySparseArray.keyAt(i)); - final PowerGaugePreference pref = (PowerGaugePreference) mAppListGroup.findPreference( - key); - if (pref != null) { - pref.shouldShowAnomalyIcon(true); - } - } + mBatteryAppListPreferenceController.refreshAppListGroup(mStatsHelper, mShowAllApps, + timeSequence); } @VisibleForTesting @@ -632,6 +404,11 @@ public class PowerUsageSummary extends PowerUsageBase implements } } + @VisibleForTesting + void setBatteryLayoutPreference(LayoutPreference layoutPreference) { + mBatteryLayoutPref = layoutPreference; + } + @VisibleForTesting AnomalyDetectionPolicy getAnomalyDetectionPolicy() { return new AnomalyDetectionPolicy(getContext()); @@ -674,54 +451,6 @@ public class PowerUsageSummary extends PowerUsageBase implements mBatteryInfoDebugLoaderCallbacks); } - @VisibleForTesting - double calculatePercentage(double powerUsage, double dischargeAmount) { - final double totalPower = mStatsHelper.getTotalPower(); - return totalPower == 0 ? 0 : - ((powerUsage / totalPower) * dischargeAmount); - } - - @VisibleForTesting - void setUsageSummary(Preference preference, BatterySipper sipper) { - // Only show summary when usage time is longer than one minute - final long usageTimeMs = sipper.usageTimeMs; - if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) { - final CharSequence timeSequence = Utils.formatElapsedTime(getContext(), usageTimeMs, - false); - preference.setSummary( - (sipper.drainType != DrainType.APP || mBatteryUtils.shouldHideSipper(sipper)) - ? timeSequence - : TextUtils.expandTemplate(getText(R.string.battery_used_for), - timeSequence)); - } - } - - @VisibleForTesting - String extractKeyFromSipper(BatterySipper sipper) { - if (sipper.uidObj != null) { - return extractKeyFromUid(sipper.getUid()); - } else if (sipper.drainType == DrainType.USER) { - return sipper.drainType.toString() + sipper.userId; - } else if (sipper.drainType != DrainType.APP) { - return sipper.drainType.toString(); - } else if (sipper.getPackages() != null) { - return TextUtils.concat(sipper.getPackages()).toString(); - } else { - Log.w(TAG, "Inappropriate BatterySipper without uid and package names: " + sipper); - return "-1"; - } - } - - @VisibleForTesting - String extractKeyFromUid(int uid) { - return Integer.toString(uid); - } - - @VisibleForTesting - void setBatteryLayoutPreference(LayoutPreference layoutPreference) { - mBatteryLayoutPref = layoutPreference; - } - @VisibleForTesting void initFeatureProvider() { final Context context = getContext(); @@ -755,72 +484,6 @@ public class PowerUsageSummary extends PowerUsageBase implements } } - private static List getFakeStats() { - ArrayList stats = new ArrayList<>(); - float use = 5; - for (DrainType type : DrainType.values()) { - if (type == DrainType.APP) { - continue; - } - stats.add(new BatterySipper(type, null, use)); - use += 5; - } - for (int i = 0; i < 100; i++) { - stats.add(new BatterySipper(DrainType.APP, - new FakeUid(Process.FIRST_APPLICATION_UID + i), use)); - } - stats.add(new BatterySipper(DrainType.APP, - new FakeUid(0), use)); - - // Simulate dex2oat process. - BatterySipper sipper = new BatterySipper(DrainType.APP, - new FakeUid(UserHandle.getSharedAppGid(Process.FIRST_APPLICATION_UID)), 10.0f); - sipper.packageWithHighestDrain = "dex2oat"; - stats.add(sipper); - - sipper = new BatterySipper(DrainType.APP, - new FakeUid(UserHandle.getSharedAppGid(Process.FIRST_APPLICATION_UID + 1)), 10.0f); - sipper.packageWithHighestDrain = "dex2oat"; - stats.add(sipper); - - sipper = new BatterySipper(DrainType.APP, - new FakeUid(UserHandle.getSharedAppGid(Process.LOG_UID)), 9.0f); - stats.add(sipper); - - return stats; - } - - Handler mHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case BatteryEntry.MSG_UPDATE_NAME_ICON: - BatteryEntry entry = (BatteryEntry) msg.obj; - PowerGaugePreference pgp = - (PowerGaugePreference) findPreference( - Integer.toString(entry.sipper.uidObj.getUid())); - if (pgp != null) { - final int userId = UserHandle.getUserId(entry.sipper.getUid()); - final UserHandle userHandle = new UserHandle(userId); - pgp.setIcon(mUm.getBadgedIconForUser(entry.getIcon(), userHandle)); - pgp.setTitle(entry.name); - if (entry.sipper.drainType == DrainType.APP) { - pgp.setContentDescription(entry.name); - } - } - break; - case BatteryEntry.MSG_REPORT_FULLY_DRAWN: - Activity activity = getActivity(); - if (activity != null) { - activity.reportFullyDrawn(); - } - break; - } - super.handleMessage(msg); - } - }; - @Override public void onAnomalyHandled(Anomaly anomaly) { mAnomalySummaryPreferenceController.hideHighUsagePreference(); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java new file mode 100644 index 00000000000..528209115ef --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.fuelgauge; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.support.v14.preference.PreferenceFragment; +import android.support.v7.preference.PreferenceGroup; +import android.text.TextUtils; +import android.text.format.DateUtils; +import android.util.SparseArray; + +import com.android.internal.os.BatterySipper; +import com.android.internal.os.BatteryStatsImpl; +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.TestConfig; +import com.android.settings.fuelgauge.anomaly.Anomaly; +import com.android.settings.testutils.FakeFeatureFactory; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class BatteryAppListPreferenceControllerTest { + private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"}; + private static final String KEY_APP_LIST = "app_list"; + private static final int UID = 123; + + @Mock + private BatterySipper mNormalBatterySipper; + @Mock + private SettingsActivity mSettingsActivity; + @Mock + private PreferenceGroup mAppListGroup; + @Mock + private PreferenceFragment mFragment; + @Mock + private BatteryUtils mBatteryUtils; + + private Context mContext; + private PowerGaugePreference mPreference; + private BatteryAppListPreferenceController mPreferenceController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + FakeFeatureFactory.setupForTest(); + + mPreference = new PowerGaugePreference(mContext); + when(mNormalBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES); + when(mNormalBatterySipper.getUid()).thenReturn(UID); + mNormalBatterySipper.drainType = BatterySipper.DrainType.APP; + + mPreferenceController = new BatteryAppListPreferenceController(mContext, KEY_APP_LIST, null, + mSettingsActivity, mFragment); + mPreferenceController.mBatteryUtils = mBatteryUtils; + mPreferenceController.mAppListGroup = mAppListGroup; + } + + @Test + public void testExtractKeyFromSipper_typeAPPUidObjectNull_returnPackageNames() { + mNormalBatterySipper.uidObj = null; + mNormalBatterySipper.drainType = BatterySipper.DrainType.APP; + + final String key = mPreferenceController.extractKeyFromSipper(mNormalBatterySipper); + assertThat(key).isEqualTo(TextUtils.concat(mNormalBatterySipper.getPackages()).toString()); + } + + @Test + public void testExtractKeyFromSipper_typeOther_returnDrainType() { + mNormalBatterySipper.uidObj = null; + mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH; + + final String key = mPreferenceController.extractKeyFromSipper(mNormalBatterySipper); + assertThat(key).isEqualTo(mNormalBatterySipper.drainType.toString()); + } + + @Test + public void testExtractKeyFromSipper_typeUser_returnDrainTypeWithUserId() { + mNormalBatterySipper.uidObj = null; + mNormalBatterySipper.drainType = BatterySipper.DrainType.USER; + mNormalBatterySipper.userId = 2; + + final String key = mPreferenceController.extractKeyFromSipper(mNormalBatterySipper); + assertThat(key).isEqualTo("USER2"); + } + + @Test + public void testExtractKeyFromSipper_typeAPPUidObjectNotNull_returnUid() { + mNormalBatterySipper.uidObj = new BatteryStatsImpl.Uid(new BatteryStatsImpl(), UID); + mNormalBatterySipper.drainType = BatterySipper.DrainType.APP; + + final String key = mPreferenceController.extractKeyFromSipper(mNormalBatterySipper); + assertThat(key).isEqualTo(Integer.toString(mNormalBatterySipper.getUid())); + } + + @Test + public void testSetUsageSummary_timeLessThanOneMinute_DoNotSetSummary() { + mNormalBatterySipper.usageTimeMs = 59 * DateUtils.SECOND_IN_MILLIS; + + mPreferenceController.setUsageSummary(mPreference, mNormalBatterySipper); + assertThat(mPreference.getSummary()).isNull(); + } + + @Test + public void testSetUsageSummary_timeMoreThanOneMinute_normalApp_setScreenSummary() { + mNormalBatterySipper.usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS; + doReturn(mContext.getText(R.string.battery_used_for)).when(mFragment).getText( + R.string.battery_used_for); + doReturn(mContext).when(mFragment).getContext(); + + mPreferenceController.setUsageSummary(mPreference, mNormalBatterySipper); + + assertThat(mPreference.getSummary().toString()).isEqualTo("Used for 2m"); + } + + @Test + public void testSetUsageSummary_timeMoreThanOneMinute_hiddenApp_setUsedSummary() { + mNormalBatterySipper.usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS; + doReturn(true).when(mBatteryUtils).shouldHideSipper(mNormalBatterySipper); + doReturn(mContext).when(mFragment).getContext(); + + mPreferenceController.setUsageSummary(mPreference, mNormalBatterySipper); + + assertThat(mPreference.getSummary().toString()).isEqualTo("2m"); + } + + @Test + public void testSetUsageSummary_timeMoreThanOneMinute_notApp_setUsedSummary() { + mNormalBatterySipper.usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS; + mNormalBatterySipper.drainType = BatterySipper.DrainType.PHONE; + doReturn(mContext).when(mFragment).getContext(); + + mPreferenceController.setUsageSummary(mPreference, mNormalBatterySipper); + + assertThat(mPreference.getSummary().toString()).isEqualTo("2m"); + } + + @Test + public void testRefreshAnomalyIcon_containsAnomaly_showAnomalyIcon() { + PowerGaugePreference preference = new PowerGaugePreference(mContext); + final String key = mPreferenceController.extractKeyFromUid(UID); + final SparseArray> anomalySparseArray = new SparseArray<>(); + anomalySparseArray.append(UID, null); + preference.setKey(key); + doReturn(preference).when(mAppListGroup).findPreference(key); + + mPreferenceController.refreshAnomalyIcon(anomalySparseArray); + + assertThat(preference.showAnomalyIcon()).isTrue(); + } + + @Test + public void testShouldHideSipper_typeOvercounted_returnTrue() { + mNormalBatterySipper.drainType = BatterySipper.DrainType.OVERCOUNTED; + + assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isTrue(); + } + + @Test + public void testShouldHideSipper_typeUnaccounted_returnTrue() { + mNormalBatterySipper.drainType = BatterySipper.DrainType.UNACCOUNTED; + + assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isTrue(); + } + + @Test + public void testShouldHideSipper_typeNormal_returnFalse() { + mNormalBatterySipper.drainType = BatterySipper.DrainType.APP; + + assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isFalse(); + } +} diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java new file mode 100644 index 00000000000..16439f43a81 --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settings.fuelgauge; + +import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS; +import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.LoaderManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.PowerManager; +import android.support.v7.preference.PreferenceScreen; +import android.util.SparseArray; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.internal.os.BatterySipper; +import com.android.internal.os.BatteryStatsHelper; +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.TestConfig; +import com.android.settings.Utils; +import com.android.settings.applications.LayoutPreference; +import com.android.settings.fuelgauge.anomaly.Anomaly; +import com.android.settings.fuelgauge.anomaly.AnomalyDetectionPolicy; +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settings.testutils.XmlTestUtils; +import com.android.settings.testutils.shadow.SettingsShadowResources; +import com.android.settingslib.core.AbstractPreferenceController; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.List; + +/** + * Unit tests for {@link PowerUsageSummary}. + */ +// TODO: Improve this test class so that it starts up the real activity and fragment. +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, + sdk = TestConfig.SDK_VERSION_O, + shadows = { + SettingsShadowResources.class, + SettingsShadowResources.SettingsShadowTheme.class, + }) +public class PowerUsageSummaryTest { + private static final String STUB_STRING = "stub_string"; + private static final int UID = 123; + private static final int UID_2 = 234; + private static final int POWER_MAH = 100; + private static final long TIME_SINCE_LAST_FULL_CHARGE_MS = 120 * 60 * 1000; + private static final long TIME_SINCE_LAST_FULL_CHARGE_US = + TIME_SINCE_LAST_FULL_CHARGE_MS * 1000; + private static final long USAGE_TIME_MS = 65 * 60 * 1000; + private static final double TOTAL_POWER = 200; + public static final String NEW_ML_EST_SUFFIX = "(New ML est)"; + public static final String OLD_EST_SUFFIX = "(Old est)"; + private static Intent sAdditionalBatteryInfoIntent; + + @BeforeClass + public static void beforeClass() { + sAdditionalBatteryInfoIntent = new Intent("com.example.app.ADDITIONAL_BATTERY_INFO"); + } + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Menu mMenu; + @Mock + private MenuItem mToggleAppsMenu; + @Mock + private MenuItem mHighPowerMenu; + @Mock + private MenuInflater mMenuInflater; + @Mock + private BatterySipper mNormalBatterySipper; + @Mock + private BatterySipper mScreenBatterySipper; + @Mock + private BatterySipper mCellBatterySipper; + @Mock + private LayoutPreference mBatteryLayoutPref; + @Mock + private TextView mBatteryPercentText; + @Mock + private TextView mSummary1; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private BatteryStatsHelper mBatteryHelper; + @Mock + private PowerManager mPowerManager; + @Mock + private SettingsActivity mSettingsActivity; + @Mock + private LoaderManager mLoaderManager; + @Mock + private PreferenceScreen mPreferenceScreen; + @Mock + private AnomalyDetectionPolicy mAnomalyDetectionPolicy; + @Mock + private BatteryHeaderPreferenceController mBatteryHeaderPreferenceController; + + private List mUsageList; + private Context mRealContext; + private TestFragment mFragment; + private FakeFeatureFactory mFeatureFactory; + private BatteryMeterView mBatteryMeterView; + private PowerGaugePreference mScreenUsagePref; + private PowerGaugePreference mLastFullChargePref; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mRealContext = RuntimeEnvironment.application; + mFeatureFactory = FakeFeatureFactory.setupForTest(); + when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager); + + mScreenUsagePref = new PowerGaugePreference(mRealContext); + mLastFullChargePref = new PowerGaugePreference(mRealContext); + mFragment = spy(new TestFragment(mContext)); + mFragment.initFeatureProvider(); + mBatteryMeterView = new BatteryMeterView(mRealContext); + mBatteryMeterView.mDrawable = new BatteryMeterView.BatteryMeterDrawable(mRealContext, 0); + doNothing().when(mFragment).restartBatteryStatsLoader(); + doReturn(mock(LoaderManager.class)).when(mFragment).getLoaderManager(); + + when(mFragment.getActivity()).thenReturn(mSettingsActivity); + when(mToggleAppsMenu.getItemId()).thenReturn(MENU_TOGGLE_APPS); + when(mHighPowerMenu.getItemId()).thenReturn(MENU_HIGH_POWER_APPS); + when(mFeatureFactory.powerUsageFeatureProvider.getAdditionalBatteryInfoIntent()) + .thenReturn(sAdditionalBatteryInfoIntent); + when(mBatteryHelper.getTotalPower()).thenReturn(TOTAL_POWER); + when(mBatteryHelper.getStats().computeBatteryRealtime(anyLong(), anyInt())).thenReturn( + TIME_SINCE_LAST_FULL_CHARGE_US); + + when(mNormalBatterySipper.getUid()).thenReturn(UID); + mNormalBatterySipper.totalPowerMah = POWER_MAH; + mNormalBatterySipper.drainType = BatterySipper.DrainType.APP; + + mCellBatterySipper.drainType = BatterySipper.DrainType.CELL; + mCellBatterySipper.totalPowerMah = POWER_MAH; + + when(mBatteryLayoutPref.findViewById(R.id.summary1)).thenReturn(mSummary1); + when(mBatteryLayoutPref.findViewById(R.id.battery_percent)).thenReturn(mBatteryPercentText); + when(mBatteryLayoutPref.findViewById(R.id.battery_header_icon)) + .thenReturn(mBatteryMeterView); + mFragment.setBatteryLayoutPreference(mBatteryLayoutPref); + + mScreenBatterySipper.drainType = BatterySipper.DrainType.SCREEN; + mScreenBatterySipper.usageTimeMs = USAGE_TIME_MS; + + mUsageList = new ArrayList<>(); + mUsageList.add(mNormalBatterySipper); + mUsageList.add(mScreenBatterySipper); + mUsageList.add(mCellBatterySipper); + + mFragment.mStatsHelper = mBatteryHelper; + when(mBatteryHelper.getUsageList()).thenReturn(mUsageList); + mFragment.mScreenUsagePref = mScreenUsagePref; + mFragment.mLastFullChargePref = mLastFullChargePref; + mFragment.mBatteryUtils = spy(new BatteryUtils(mRealContext)); + } + + @Test + public void testOptionsMenu_menuHighPower_metricEventInvoked() { + mFragment.onOptionsItemSelected(mHighPowerMenu); + + verify(mFeatureFactory.metricsFeatureProvider).action(mContext, + MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_OPTIMIZATION); + } + + @Test + public void testOptionsMenu_menuAppToggle_metricEventInvoked() { + mFragment.onOptionsItemSelected(mToggleAppsMenu); + mFragment.mShowAllApps = false; + + verify(mFeatureFactory.metricsFeatureProvider).action(mContext, + MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE, true); + } + + @Test + public void testOptionsMenu_toggleAppsEnabled() { + when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled()) + .thenReturn(true); + mFragment.mShowAllApps = false; + + mFragment.onCreateOptionsMenu(mMenu, mMenuInflater); + + verify(mMenu).add(Menu.NONE, MENU_TOGGLE_APPS, Menu.NONE, R.string.show_all_apps); + } + + @Test + public void testOptionsMenu_clickToggleAppsMenu_dataChanged() { + testToggleAllApps(true); + testToggleAllApps(false); + } + + private void testToggleAllApps(final boolean isShowApps) { + mFragment.mShowAllApps = isShowApps; + + mFragment.onOptionsItemSelected(mToggleAppsMenu); + assertThat(mFragment.mShowAllApps).isEqualTo(!isShowApps); + } + + @Test + public void testFindBatterySipperByType_findTypeScreen() { + BatterySipper sipper = mFragment.findBatterySipperByType(mUsageList, + BatterySipper.DrainType.SCREEN); + + assertThat(sipper).isSameAs(mScreenBatterySipper); + } + + @Test + public void testFindBatterySipperByType_findTypeApp() { + BatterySipper sipper = mFragment.findBatterySipperByType(mUsageList, + BatterySipper.DrainType.APP); + + assertThat(sipper).isSameAs(mNormalBatterySipper); + } + + @Test + public void testUpdateScreenPreference_showCorrectSummary() { + doReturn(mScreenBatterySipper).when(mFragment).findBatterySipperByType(any(), any()); + doReturn(mRealContext).when(mFragment).getContext(); + final CharSequence expectedSummary = Utils.formatElapsedTime(mRealContext, USAGE_TIME_MS, + false); + + mFragment.updateScreenPreference(); + + assertThat(mScreenUsagePref.getSubtitle()).isEqualTo(expectedSummary); + } + + @Test + public void testUpdateLastFullChargePreference_showCorrectSummary() { + doReturn(mRealContext).when(mFragment).getContext(); + + mFragment.updateLastFullChargePreference(TIME_SINCE_LAST_FULL_CHARGE_MS); + + assertThat(mLastFullChargePref.getSubtitle()).isEqualTo("2 hr. ago"); + } + + @Test + public void testUpdatePreference_usageListEmpty_shouldNotCrash() { + when(mBatteryHelper.getUsageList()).thenReturn(new ArrayList()); + doReturn(STUB_STRING).when(mFragment).getString(anyInt(), any()); + doReturn(mRealContext).when(mFragment).getContext(); + + // Should not crash when update + mFragment.updateScreenPreference(); + } + + @Test + public void testNonIndexableKeys_MatchPreferenceKeys() { + final Context context = RuntimeEnvironment.application; + final List niks = PowerUsageSummary.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(context); + + final List keys = XmlTestUtils.getKeysFromPreferenceXml(context, + R.xml.power_usage_summary); + + assertThat(keys).containsAllIn(niks); + } + + @Test + public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() { + final Context context = RuntimeEnvironment.application; + final PowerUsageSummary fragment = new PowerUsageSummary(); + final List preferenceScreenKeys = XmlTestUtils.getKeysFromPreferenceXml(context, + fragment.getPreferenceScreenResId()); + final List preferenceKeys = new ArrayList<>(); + + for (AbstractPreferenceController controller : fragment.getPreferenceControllers(context)) { + preferenceKeys.add(controller.getPreferenceKey()); + } + + assertThat(preferenceScreenKeys).containsAllIn(preferenceKeys); + } + + @Test + public void testUpdateAnomalySparseArray() { + mFragment.mAnomalySparseArray = new SparseArray<>(); + final List anomalies = new ArrayList<>(); + final Anomaly anomaly1 = new Anomaly.Builder().setUid(UID).build(); + final Anomaly anomaly2 = new Anomaly.Builder().setUid(UID).build(); + final Anomaly anomaly3 = new Anomaly.Builder().setUid(UID_2).build(); + anomalies.add(anomaly1); + anomalies.add(anomaly2); + anomalies.add(anomaly3); + + mFragment.updateAnomalySparseArray(anomalies); + + assertThat(mFragment.mAnomalySparseArray.get(UID)).containsExactly(anomaly1, anomaly2); + assertThat(mFragment.mAnomalySparseArray.get(UID_2)).containsExactly(anomaly3); + } + + @Test + public void testInitAnomalyDetectionIfPossible_detectionEnabled_init() { + doReturn(mLoaderManager).when(mFragment).getLoaderManager(); + doReturn(mAnomalyDetectionPolicy).when(mFragment).getAnomalyDetectionPolicy(); + when(mAnomalyDetectionPolicy.isAnomalyDetectionEnabled()).thenReturn(true); + + mFragment.restartAnomalyDetectionIfPossible(); + + verify(mLoaderManager).restartLoader(eq(PowerUsageSummary.ANOMALY_LOADER), eq(Bundle.EMPTY), + any()); + } + + @Test + public void testShowBothEstimates_summariesAreBothModified() { + doReturn(new TextView(mRealContext)).when(mBatteryLayoutPref).findViewById(R.id.summary2); + doReturn(new TextView(mRealContext)).when(mBatteryLayoutPref).findViewById(R.id.summary1); + mFragment.onLongClick(new View(mRealContext)); + TextView summary1 = mFragment.mBatteryLayoutPref.findViewById(R.id.summary1); + TextView summary2 = mFragment.mBatteryLayoutPref.findViewById(R.id.summary2); + Robolectric.flushBackgroundThreadScheduler(); + assertThat(summary2.getText().toString().contains(NEW_ML_EST_SUFFIX)); + assertThat(summary1.getText().toString().contains(OLD_EST_SUFFIX)); + } + + @Test + public void testSaveInstanceState_showAllAppsRestored() { + Bundle bundle = new Bundle(); + mFragment.mShowAllApps = true; + doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen(); + + mFragment.onSaveInstanceState(bundle); + mFragment.restoreSavedInstance(bundle); + + assertThat(mFragment.mShowAllApps).isTrue(); + } + + @Test + public void testDebugMode() { + doReturn(true).when(mFeatureFactory.powerUsageFeatureProvider).isEstimateDebugEnabled(); + + mFragment.restartBatteryInfoLoader(); + ArgumentCaptor listener = ArgumentCaptor.forClass( + View.OnLongClickListener.class); + verify(mSummary1).setOnLongClickListener(listener.capture()); + + // Calling the listener should disable it. + listener.getValue().onLongClick(mSummary1); + verify(mSummary1).setOnLongClickListener(null); + + // Restarting the loader should reset the listener. + mFragment.restartBatteryInfoLoader(); + verify(mSummary1, times(2)).setOnLongClickListener(any(View.OnLongClickListener.class)); + } + + @Test + public void testRestartBatteryStatsLoader_notClearHeader_quickUpdateNotInvoked() { + mFragment.mBatteryHeaderPreferenceController = mBatteryHeaderPreferenceController; + + mFragment.restartBatteryStatsLoader(false /* clearHeader */); + + verify(mBatteryHeaderPreferenceController, never()).quickUpdateHeaderPreference(); + } + + public static class TestFragment extends PowerUsageSummary { + private Context mContext; + + public TestFragment(Context context) { + mContext = context; + } + + @Override + public Context getContext() { + return mContext; + } + + + @Override + protected void refreshUi() { + // Leave it empty for toggle apps menu test + } + } +} From 8f73968308df6057edf6f812989327e347d1054f Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Thu, 7 Dec 2017 15:41:48 -0800 Subject: [PATCH 12/13] Add feature flag to control battery app list. If feature flag is on, then display the app list. Otherwise disable it. Bug: 70234293 Test: RunSettingsRoboTests Change-Id: I1663f925abf95e0e4c1a46d98ca165303a76e979 --- .../android/settings/core/FeatureFlags.java | 1 + .../BatteryAppListPreferenceController.java | 4 +++- ...atteryAppListPreferenceControllerTest.java | 21 ++++++++++++++++++- .../fuelgauge/PowerUsageSummaryTest.java | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java index 197876fcb17..9ceef47c06a 100644 --- a/src/com/android/settings/core/FeatureFlags.java +++ b/src/com/android/settings/core/FeatureFlags.java @@ -26,4 +26,5 @@ public class FeatureFlags { public static final String APP_INFO_V2 = "settings_app_info_v2"; public static final String CONNECTED_DEVICE_V2 = "settings_connected_device_v2"; public static final String BATTERY_SETTINGS_V2 = "settings_battery_v2"; + public static final String BATTERY_DISPLAY_APP_LIST = "settings_battery_display_app_list"; } diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java index ee0ed212f99..5d95dd2ec71 100644 --- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java @@ -36,6 +36,7 @@ import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; +import android.util.FeatureFlagUtils; import android.util.Log; import android.util.SparseArray; @@ -45,6 +46,7 @@ import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.PowerProfile; import com.android.settings.R; import com.android.settings.SettingsActivity; +import com.android.settings.core.FeatureFlags; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.Utils; import com.android.settings.core.instrumentation.MetricsFeatureProvider; @@ -149,7 +151,7 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro @Override public boolean isAvailable() { - return false; + return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST); } @Override diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java index 528209115ef..a814989a405 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryAppListPreferenceControllerTest.java @@ -27,6 +27,7 @@ import android.support.v14.preference.PreferenceFragment; import android.support.v7.preference.PreferenceGroup; import android.text.TextUtils; import android.text.format.DateUtils; +import android.util.FeatureFlagUtils; import android.util.SparseArray; import com.android.internal.os.BatterySipper; @@ -34,8 +35,10 @@ import com.android.internal.os.BatteryStatsImpl; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.TestConfig; +import com.android.settings.core.FeatureFlags; import com.android.settings.fuelgauge.anomaly.Anomaly; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.SettingsShadowSystemProperties; import org.junit.Before; import org.junit.Test; @@ -49,7 +52,8 @@ import org.robolectric.annotation.Config; import java.util.List; @RunWith(RobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = + SettingsShadowSystemProperties.class) public class BatteryAppListPreferenceControllerTest { private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"}; private static final String KEY_APP_LIST = "app_list"; @@ -169,6 +173,7 @@ public class BatteryAppListPreferenceControllerTest { @Test public void testRefreshAnomalyIcon_containsAnomaly_showAnomalyIcon() { + FeatureFlagUtils.setEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST, true); PowerGaugePreference preference = new PowerGaugePreference(mContext); final String key = mPreferenceController.extractKeyFromUid(UID); final SparseArray> anomalySparseArray = new SparseArray<>(); @@ -201,4 +206,18 @@ public class BatteryAppListPreferenceControllerTest { assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isFalse(); } + + @Test + public void testIsAvailable_featureOn_returnTrue() { + FeatureFlagUtils.setEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST, true); + + assertThat(mPreferenceController.isAvailable()).isTrue(); + } + + @Test + public void testIsAvailable_featureOff_returnFalse() { + FeatureFlagUtils.setEnabled(mContext, FeatureFlags.BATTERY_DISPLAY_APP_LIST, false); + + assertThat(mPreferenceController.isAvailable()).isFalse(); + } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java index 16439f43a81..0ca983f3f80 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java @@ -83,7 +83,7 @@ import java.util.List; // TODO: Improve this test class so that it starts up the real activity and fragment. @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, - sdk = TestConfig.SDK_VERSION_O, + sdk = TestConfig.SDK_VERSION, shadows = { SettingsShadowResources.class, SettingsShadowResources.SettingsShadowTheme.class, From 2baf72190c0271c617bad5582ca5269767c03fb1 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 8 Dec 2017 00:02:43 +0000 Subject: [PATCH 13/13] Stop statically including legacy-android-test Statically including legacy-android-test leads to duplicate classes which causes build time problems (with Proguard) and runtime problems on older SDK versions. This change: * Stops statically including legacy-android-test. * Adds compile time dependencies on andoid.test.base, android.test.mock and android.test.runner where necessary. * Adds to any affected package to ensure that the classes that were included by legacy-android-test are still available at runtime. That also adds a dependency on android.test.base and android.test.mock. The following change descriptions were generated automatically and so may be a little repetitive. They are provided to give the reviewer enough information to check the comments match what has actually been changed and check the reasoning behind the changes. * tests/unit/Android.mk Added 'android.test.base' and 'android.test.mock' to LOCAL_JAVA_LIBRARIES because SettingsUnitTests's source depends on their classes and because of these changes they are no longer present on the compilation path. Removed legacy-android-test from LOCAL_STATIC_JAVA_LIBRARIES because statically including the classes in SettingsUnitTests results in duplicate classes which leads to build time and compile time issues. Bug: 30188076 Test: make checkbuild Change-Id: I191a72e50017213df6ad04f32aa660e8028720e2 --- tests/unit/Android.mk | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk index 58fe7dd1d21..cbf91dbab73 100644 --- a/tests/unit/Android.mk +++ b/tests/unit/Android.mk @@ -5,14 +5,19 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests LOCAL_CERTIFICATE := platform -LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common ims-common +LOCAL_JAVA_LIBRARIES := \ + android.test.runner \ + telephony-common \ + ims-common \ + android.test.base \ + android.test.mock \ + LOCAL_STATIC_JAVA_LIBRARIES := \ android-support-test \ espresso-core \ espresso-contrib-nodep \ espresso-intents-nodep \ - legacy-android-test \ mockito-target-minus-junit4 \ platform-test-annotations \ truth-prebuilt \