summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--adb_install.cpp2
-rw-r--r--device.cpp4
-rw-r--r--device.h1
-rw-r--r--edify/Android.mk4
-rw-r--r--edify/expr.cpp39
-rw-r--r--edify/expr.h18
-rw-r--r--error_code.h46
-rw-r--r--install.cpp54
-rw-r--r--install.h4
-rwxr-xr-x[-rw-r--r--]interlace-frames.py62
-rw-r--r--minui/minui.h2
-rw-r--r--minui/resources.cpp23
-rw-r--r--minzip/SysUtil.c67
-rw-r--r--otafault/Android.mk9
-rw-r--r--otafault/ota_io.cpp3
-rw-r--r--print_sha1.h6
-rw-r--r--recovery.cpp86
l---------res-560dpi2
-rw-r--r--res-hdpi/images/erasing_text.pngbin20528 -> 55181 bytes
-rw-r--r--res-hdpi/images/error_text.pngbin11684 -> 39052 bytes
-rw-r--r--res-hdpi/images/icon_installing.pngbin129975 -> 0 bytes
-rw-r--r--res-hdpi/images/installing_security_text.pngbin0 -> 122186 bytes
-rw-r--r--res-hdpi/images/installing_text.pngbin40946 -> 113078 bytes
-rw-r--r--res-hdpi/images/loop00000.pngbin0 -> 9715 bytes
-rw-r--r--res-hdpi/images/loop00001.pngbin0 -> 9823 bytes
-rw-r--r--res-hdpi/images/loop00002.pngbin0 -> 9807 bytes
-rw-r--r--res-hdpi/images/loop00003.pngbin0 -> 9748 bytes
-rw-r--r--res-hdpi/images/loop00004.pngbin0 -> 9966 bytes
-rw-r--r--res-hdpi/images/loop00005.pngbin0 -> 10030 bytes
-rw-r--r--res-hdpi/images/loop00006.pngbin0 -> 10211 bytes
-rw-r--r--res-hdpi/images/loop00007.pngbin0 -> 10300 bytes
-rw-r--r--res-hdpi/images/loop00008.pngbin0 -> 10271 bytes
-rw-r--r--res-hdpi/images/loop00009.pngbin0 -> 10172 bytes
-rw-r--r--res-hdpi/images/loop00010.pngbin0 -> 10252 bytes
-rw-r--r--res-hdpi/images/loop00011.pngbin0 -> 10194 bytes
-rw-r--r--res-hdpi/images/loop00012.pngbin0 -> 10246 bytes
-rw-r--r--res-hdpi/images/loop00013.pngbin0 -> 10280 bytes
-rw-r--r--res-hdpi/images/loop00014.pngbin0 -> 10263 bytes
-rw-r--r--res-hdpi/images/loop00015.pngbin0 -> 10214 bytes
-rw-r--r--res-hdpi/images/loop00016.pngbin0 -> 10308 bytes
-rw-r--r--res-hdpi/images/loop00017.pngbin0 -> 10082 bytes
-rw-r--r--res-hdpi/images/loop00018.pngbin0 -> 10115 bytes
-rw-r--r--res-hdpi/images/loop00019.pngbin0 -> 10004 bytes
-rw-r--r--res-hdpi/images/loop00020.pngbin0 -> 9793 bytes
-rw-r--r--res-hdpi/images/loop00021.pngbin0 -> 9952 bytes
-rw-r--r--res-hdpi/images/loop00022.pngbin0 -> 9784 bytes
-rw-r--r--res-hdpi/images/loop00023.pngbin0 -> 9758 bytes
-rw-r--r--res-hdpi/images/loop00024.pngbin0 -> 9738 bytes
-rw-r--r--res-hdpi/images/loop00025.pngbin0 -> 9716 bytes
-rw-r--r--res-hdpi/images/loop00026.pngbin0 -> 9912 bytes
-rw-r--r--res-hdpi/images/loop00027.pngbin0 -> 9716 bytes
-rw-r--r--res-hdpi/images/loop00028.pngbin0 -> 10005 bytes
-rw-r--r--res-hdpi/images/loop00029.pngbin0 -> 10038 bytes
-rw-r--r--res-hdpi/images/loop00030.pngbin0 -> 9975 bytes
-rw-r--r--res-hdpi/images/loop00031.pngbin0 -> 9855 bytes
-rw-r--r--res-hdpi/images/loop00032.pngbin0 -> 9743 bytes
-rw-r--r--res-hdpi/images/loop00033.pngbin0 -> 9989 bytes
-rw-r--r--res-hdpi/images/loop00034.pngbin0 -> 10005 bytes
-rw-r--r--res-hdpi/images/loop00035.pngbin0 -> 10192 bytes
-rw-r--r--res-hdpi/images/loop00036.pngbin0 -> 10112 bytes
-rw-r--r--res-hdpi/images/loop00037.pngbin0 -> 10325 bytes
-rw-r--r--res-hdpi/images/loop00038.pngbin0 -> 10477 bytes
-rw-r--r--res-hdpi/images/loop00039.pngbin0 -> 10458 bytes
-rw-r--r--res-hdpi/images/loop00040.pngbin0 -> 10381 bytes
-rw-r--r--res-hdpi/images/loop00041.pngbin0 -> 10791 bytes
-rw-r--r--res-hdpi/images/loop00042.pngbin0 -> 10753 bytes
-rw-r--r--res-hdpi/images/loop00043.pngbin0 -> 10721 bytes
-rw-r--r--res-hdpi/images/loop00044.pngbin0 -> 10763 bytes
-rw-r--r--res-hdpi/images/loop00045.pngbin0 -> 10839 bytes
-rw-r--r--res-hdpi/images/loop00046.pngbin0 -> 10883 bytes
-rw-r--r--res-hdpi/images/loop00047.pngbin0 -> 11049 bytes
-rw-r--r--res-hdpi/images/loop00048.pngbin0 -> 10971 bytes
-rw-r--r--res-hdpi/images/loop00049.pngbin0 -> 11018 bytes
-rw-r--r--res-hdpi/images/loop00050.pngbin0 -> 10662 bytes
-rw-r--r--res-hdpi/images/loop00051.pngbin0 -> 10500 bytes
-rw-r--r--res-hdpi/images/loop00052.pngbin0 -> 10593 bytes
-rw-r--r--res-hdpi/images/loop00053.pngbin0 -> 10591 bytes
-rw-r--r--res-hdpi/images/loop00054.pngbin0 -> 10594 bytes
-rw-r--r--res-hdpi/images/loop00055.pngbin0 -> 10338 bytes
-rw-r--r--res-hdpi/images/loop00056.pngbin0 -> 10291 bytes
-rw-r--r--res-hdpi/images/loop00057.pngbin0 -> 10227 bytes
-rw-r--r--res-hdpi/images/loop00058.pngbin0 -> 10082 bytes
-rw-r--r--res-hdpi/images/loop00059.pngbin0 -> 9914 bytes
-rw-r--r--res-hdpi/images/loop00060.pngbin0 -> 10011 bytes
-rw-r--r--res-hdpi/images/loop00061.pngbin0 -> 9884 bytes
-rw-r--r--res-hdpi/images/loop00062.pngbin0 -> 9943 bytes
-rw-r--r--res-hdpi/images/loop00063.pngbin0 -> 9961 bytes
-rw-r--r--res-hdpi/images/loop00064.pngbin0 -> 9965 bytes
-rw-r--r--res-hdpi/images/loop00065.pngbin0 -> 9969 bytes
-rw-r--r--res-hdpi/images/loop00066.pngbin0 -> 9816 bytes
-rw-r--r--res-hdpi/images/loop00067.pngbin0 -> 10008 bytes
-rw-r--r--res-hdpi/images/loop00068.pngbin0 -> 9980 bytes
-rw-r--r--res-hdpi/images/loop00069.pngbin0 -> 9829 bytes
-rw-r--r--res-hdpi/images/loop00070.pngbin0 -> 10000 bytes
-rw-r--r--res-hdpi/images/loop00071.pngbin0 -> 9831 bytes
-rw-r--r--res-hdpi/images/loop00072.pngbin0 -> 9641 bytes
-rw-r--r--res-hdpi/images/loop00073.pngbin0 -> 9616 bytes
-rw-r--r--res-hdpi/images/loop00074.pngbin0 -> 9440 bytes
-rw-r--r--res-hdpi/images/loop00075.pngbin0 -> 9238 bytes
-rw-r--r--res-hdpi/images/loop00076.pngbin0 -> 9244 bytes
-rw-r--r--res-hdpi/images/loop00077.pngbin0 -> 9056 bytes
-rw-r--r--res-hdpi/images/loop00078.pngbin0 -> 9027 bytes
-rw-r--r--res-hdpi/images/loop00079.pngbin0 -> 9030 bytes
-rw-r--r--res-hdpi/images/loop00080.pngbin0 -> 9251 bytes
-rw-r--r--res-hdpi/images/loop00081.pngbin0 -> 9435 bytes
-rw-r--r--res-hdpi/images/loop00082.pngbin0 -> 9672 bytes
-rw-r--r--res-hdpi/images/loop00083.pngbin0 -> 9581 bytes
-rw-r--r--res-hdpi/images/loop00084.pngbin0 -> 9684 bytes
-rw-r--r--res-hdpi/images/loop00085.pngbin0 -> 9824 bytes
-rw-r--r--res-hdpi/images/loop00086.pngbin0 -> 9833 bytes
-rw-r--r--res-hdpi/images/loop00087.pngbin0 -> 9827 bytes
-rw-r--r--res-hdpi/images/loop00088.pngbin0 -> 9772 bytes
-rw-r--r--res-hdpi/images/loop00089.pngbin0 -> 9626 bytes
-rw-r--r--res-hdpi/images/loop00090.pngbin0 -> 9715 bytes
-rw-r--r--res-hdpi/images/no_command_text.pngbin25013 -> 67427 bytes
-rw-r--r--res-hdpi/images/progress_empty.pngbin118 -> 113 bytes
-rw-r--r--res-hdpi/images/progress_fill.pngbin404 -> 113 bytes
-rw-r--r--res-mdpi/images/erasing_text.pngbin12208 -> 31323 bytes
-rw-r--r--res-mdpi/images/error_text.pngbin7202 -> 22467 bytes
-rw-r--r--res-mdpi/images/icon_installing.pngbin129975 -> 0 bytes
-rw-r--r--res-mdpi/images/installing_security_text.pngbin0 -> 74376 bytes
-rw-r--r--res-mdpi/images/installing_text.pngbin24575 -> 66242 bytes
-rw-r--r--res-mdpi/images/loop00000.pngbin0 -> 6155 bytes
-rw-r--r--res-mdpi/images/loop00001.pngbin0 -> 6135 bytes
-rw-r--r--res-mdpi/images/loop00002.pngbin0 -> 6122 bytes
-rw-r--r--res-mdpi/images/loop00003.pngbin0 -> 6181 bytes
-rw-r--r--res-mdpi/images/loop00004.pngbin0 -> 6224 bytes
-rw-r--r--res-mdpi/images/loop00005.pngbin0 -> 6280 bytes
-rw-r--r--res-mdpi/images/loop00006.pngbin0 -> 6318 bytes
-rw-r--r--res-mdpi/images/loop00007.pngbin0 -> 6345 bytes
-rw-r--r--res-mdpi/images/loop00008.pngbin0 -> 6382 bytes
-rw-r--r--res-mdpi/images/loop00009.pngbin0 -> 6406 bytes
-rw-r--r--res-mdpi/images/loop00010.pngbin0 -> 6299 bytes
-rw-r--r--res-mdpi/images/loop00011.pngbin0 -> 6373 bytes
-rw-r--r--res-mdpi/images/loop00012.pngbin0 -> 6269 bytes
-rw-r--r--res-mdpi/images/loop00013.pngbin0 -> 6351 bytes
-rw-r--r--res-mdpi/images/loop00014.pngbin0 -> 6257 bytes
-rw-r--r--res-mdpi/images/loop00015.pngbin0 -> 6288 bytes
-rw-r--r--res-mdpi/images/loop00016.pngbin0 -> 6273 bytes
-rw-r--r--res-mdpi/images/loop00017.pngbin0 -> 6228 bytes
-rw-r--r--res-mdpi/images/loop00018.pngbin0 -> 6248 bytes
-rw-r--r--res-mdpi/images/loop00019.pngbin0 -> 6116 bytes
-rw-r--r--res-mdpi/images/loop00020.pngbin0 -> 6031 bytes
-rw-r--r--res-mdpi/images/loop00021.pngbin0 -> 6036 bytes
-rw-r--r--res-mdpi/images/loop00022.pngbin0 -> 6049 bytes
-rw-r--r--res-mdpi/images/loop00023.pngbin0 -> 6077 bytes
-rw-r--r--res-mdpi/images/loop00024.pngbin0 -> 5992 bytes
-rw-r--r--res-mdpi/images/loop00025.pngbin0 -> 6007 bytes
-rw-r--r--res-mdpi/images/loop00026.pngbin0 -> 6029 bytes
-rw-r--r--res-mdpi/images/loop00027.pngbin0 -> 5993 bytes
-rw-r--r--res-mdpi/images/loop00028.pngbin0 -> 6004 bytes
-rw-r--r--res-mdpi/images/loop00029.pngbin0 -> 6146 bytes
-rw-r--r--res-mdpi/images/loop00030.pngbin0 -> 6196 bytes
-rw-r--r--res-mdpi/images/loop00031.pngbin0 -> 6134 bytes
-rw-r--r--res-mdpi/images/loop00032.pngbin0 -> 6114 bytes
-rw-r--r--res-mdpi/images/loop00033.pngbin0 -> 6083 bytes
-rw-r--r--res-mdpi/images/loop00034.pngbin0 -> 6132 bytes
-rw-r--r--res-mdpi/images/loop00035.pngbin0 -> 6239 bytes
-rw-r--r--res-mdpi/images/loop00036.pngbin0 -> 6260 bytes
-rw-r--r--res-mdpi/images/loop00037.pngbin0 -> 6317 bytes
-rw-r--r--res-mdpi/images/loop00038.pngbin0 -> 6424 bytes
-rw-r--r--res-mdpi/images/loop00039.pngbin0 -> 6479 bytes
-rw-r--r--res-mdpi/images/loop00040.pngbin0 -> 6515 bytes
-rw-r--r--res-mdpi/images/loop00041.pngbin0 -> 6643 bytes
-rw-r--r--res-mdpi/images/loop00042.pngbin0 -> 6654 bytes
-rw-r--r--res-mdpi/images/loop00043.pngbin0 -> 6619 bytes
-rw-r--r--res-mdpi/images/loop00044.pngbin0 -> 6730 bytes
-rw-r--r--res-mdpi/images/loop00045.pngbin0 -> 6622 bytes
-rw-r--r--res-mdpi/images/loop00046.pngbin0 -> 6683 bytes
-rw-r--r--res-mdpi/images/loop00047.pngbin0 -> 6655 bytes
-rw-r--r--res-mdpi/images/loop00048.pngbin0 -> 6768 bytes
-rw-r--r--res-mdpi/images/loop00049.pngbin0 -> 6671 bytes
-rw-r--r--res-mdpi/images/loop00050.pngbin0 -> 6572 bytes
-rw-r--r--res-mdpi/images/loop00051.pngbin0 -> 6551 bytes
-rw-r--r--res-mdpi/images/loop00052.pngbin0 -> 6561 bytes
-rw-r--r--res-mdpi/images/loop00053.pngbin0 -> 6486 bytes
-rw-r--r--res-mdpi/images/loop00054.pngbin0 -> 6559 bytes
-rw-r--r--res-mdpi/images/loop00055.pngbin0 -> 6498 bytes
-rw-r--r--res-mdpi/images/loop00056.pngbin0 -> 6369 bytes
-rw-r--r--res-mdpi/images/loop00057.pngbin0 -> 6336 bytes
-rw-r--r--res-mdpi/images/loop00058.pngbin0 -> 6329 bytes
-rw-r--r--res-mdpi/images/loop00059.pngbin0 -> 6261 bytes
-rw-r--r--res-mdpi/images/loop00060.pngbin0 -> 6168 bytes
-rw-r--r--res-mdpi/images/loop00061.pngbin0 -> 6161 bytes
-rw-r--r--res-mdpi/images/loop00062.pngbin0 -> 6185 bytes
-rw-r--r--res-mdpi/images/loop00063.pngbin0 -> 6235 bytes
-rw-r--r--res-mdpi/images/loop00064.pngbin0 -> 6226 bytes
-rw-r--r--res-mdpi/images/loop00065.pngbin0 -> 6280 bytes
-rw-r--r--res-mdpi/images/loop00066.pngbin0 -> 6167 bytes
-rw-r--r--res-mdpi/images/loop00067.pngbin0 -> 6161 bytes
-rw-r--r--res-mdpi/images/loop00068.pngbin0 -> 6234 bytes
-rw-r--r--res-mdpi/images/loop00069.pngbin0 -> 6190 bytes
-rw-r--r--res-mdpi/images/loop00070.pngbin0 -> 6168 bytes
-rw-r--r--res-mdpi/images/loop00071.pngbin0 -> 6083 bytes
-rw-r--r--res-mdpi/images/loop00072.pngbin0 -> 5992 bytes
-rw-r--r--res-mdpi/images/loop00073.pngbin0 -> 5967 bytes
-rw-r--r--res-mdpi/images/loop00074.pngbin0 -> 5818 bytes
-rw-r--r--res-mdpi/images/loop00075.pngbin0 -> 5717 bytes
-rw-r--r--res-mdpi/images/loop00076.pngbin0 -> 5724 bytes
-rw-r--r--res-mdpi/images/loop00077.pngbin0 -> 5644 bytes
-rw-r--r--res-mdpi/images/loop00078.pngbin0 -> 5660 bytes
-rw-r--r--res-mdpi/images/loop00079.pngbin0 -> 5670 bytes
-rw-r--r--res-mdpi/images/loop00080.pngbin0 -> 5718 bytes
-rw-r--r--res-mdpi/images/loop00081.pngbin0 -> 5872 bytes
-rw-r--r--res-mdpi/images/loop00082.pngbin0 -> 5929 bytes
-rw-r--r--res-mdpi/images/loop00083.pngbin0 -> 6009 bytes
-rw-r--r--res-mdpi/images/loop00084.pngbin0 -> 5988 bytes
-rw-r--r--res-mdpi/images/loop00085.pngbin0 -> 6026 bytes
-rw-r--r--res-mdpi/images/loop00086.pngbin0 -> 6021 bytes
-rw-r--r--res-mdpi/images/loop00087.pngbin0 -> 6163 bytes
-rw-r--r--res-mdpi/images/loop00088.pngbin0 -> 6127 bytes
-rw-r--r--res-mdpi/images/loop00089.pngbin0 -> 6243 bytes
-rw-r--r--res-mdpi/images/loop00090.pngbin0 -> 6155 bytes
-rw-r--r--res-mdpi/images/no_command_text.pngbin14168 -> 36416 bytes
-rw-r--r--res-mdpi/images/progress_empty.pngbin118 -> 113 bytes
-rw-r--r--res-mdpi/images/progress_fill.pngbin404 -> 113 bytes
-rw-r--r--res-xhdpi/images/erasing_text.pngbin29674 -> 80047 bytes
-rw-r--r--res-xhdpi/images/error_text.pngbin16599 -> 57974 bytes
-rw-r--r--res-xhdpi/images/icon_installing.pngbin129975 -> 0 bytes
-rw-r--r--res-xhdpi/images/installing_security_text.pngbin0 -> 212335 bytes
-rw-r--r--res-xhdpi/images/installing_text.pngbin63220 -> 191771 bytes
-rw-r--r--res-xhdpi/images/loop00000.pngbin0 -> 13121 bytes
-rw-r--r--res-xhdpi/images/loop00001.pngbin0 -> 12986 bytes
-rw-r--r--res-xhdpi/images/loop00002.pngbin0 -> 13588 bytes
-rw-r--r--res-xhdpi/images/loop00003.pngbin0 -> 13584 bytes
-rw-r--r--res-xhdpi/images/loop00004.pngbin0 -> 13685 bytes
-rw-r--r--res-xhdpi/images/loop00005.pngbin0 -> 13802 bytes
-rw-r--r--res-xhdpi/images/loop00006.pngbin0 -> 14188 bytes
-rw-r--r--res-xhdpi/images/loop00007.pngbin0 -> 14027 bytes
-rw-r--r--res-xhdpi/images/loop00008.pngbin0 -> 14273 bytes
-rw-r--r--res-xhdpi/images/loop00009.pngbin0 -> 14122 bytes
-rw-r--r--res-xhdpi/images/loop00010.pngbin0 -> 14226 bytes
-rw-r--r--res-xhdpi/images/loop00011.pngbin0 -> 14155 bytes
-rw-r--r--res-xhdpi/images/loop00012.pngbin0 -> 14375 bytes
-rw-r--r--res-xhdpi/images/loop00013.pngbin0 -> 14231 bytes
-rw-r--r--res-xhdpi/images/loop00014.pngbin0 -> 14037 bytes
-rw-r--r--res-xhdpi/images/loop00015.pngbin0 -> 14052 bytes
-rw-r--r--res-xhdpi/images/loop00016.pngbin0 -> 13930 bytes
-rw-r--r--res-xhdpi/images/loop00017.pngbin0 -> 14127 bytes
-rw-r--r--res-xhdpi/images/loop00018.pngbin0 -> 14157 bytes
-rw-r--r--res-xhdpi/images/loop00019.pngbin0 -> 13666 bytes
-rw-r--r--res-xhdpi/images/loop00020.pngbin0 -> 13677 bytes
-rw-r--r--res-xhdpi/images/loop00021.pngbin0 -> 13777 bytes
-rw-r--r--res-xhdpi/images/loop00022.pngbin0 -> 13546 bytes
-rw-r--r--res-xhdpi/images/loop00023.pngbin0 -> 13674 bytes
-rw-r--r--res-xhdpi/images/loop00024.pngbin0 -> 13465 bytes
-rw-r--r--res-xhdpi/images/loop00025.pngbin0 -> 13421 bytes
-rw-r--r--res-xhdpi/images/loop00026.pngbin0 -> 13507 bytes
-rw-r--r--res-xhdpi/images/loop00027.pngbin0 -> 13272 bytes
-rw-r--r--res-xhdpi/images/loop00028.pngbin0 -> 13692 bytes
-rw-r--r--res-xhdpi/images/loop00029.pngbin0 -> 13709 bytes
-rw-r--r--res-xhdpi/images/loop00030.pngbin0 -> 13650 bytes
-rw-r--r--res-xhdpi/images/loop00031.pngbin0 -> 13519 bytes
-rw-r--r--res-xhdpi/images/loop00032.pngbin0 -> 13523 bytes
-rw-r--r--res-xhdpi/images/loop00033.pngbin0 -> 13526 bytes
-rw-r--r--res-xhdpi/images/loop00034.pngbin0 -> 13751 bytes
-rw-r--r--res-xhdpi/images/loop00035.pngbin0 -> 14005 bytes
-rw-r--r--res-xhdpi/images/loop00036.pngbin0 -> 14137 bytes
-rw-r--r--res-xhdpi/images/loop00037.pngbin0 -> 14320 bytes
-rw-r--r--res-xhdpi/images/loop00038.pngbin0 -> 14322 bytes
-rw-r--r--res-xhdpi/images/loop00039.pngbin0 -> 14536 bytes
-rw-r--r--res-xhdpi/images/loop00040.pngbin0 -> 14550 bytes
-rw-r--r--res-xhdpi/images/loop00041.pngbin0 -> 14691 bytes
-rw-r--r--res-xhdpi/images/loop00042.pngbin0 -> 14935 bytes
-rw-r--r--res-xhdpi/images/loop00043.pngbin0 -> 14884 bytes
-rw-r--r--res-xhdpi/images/loop00044.pngbin0 -> 14958 bytes
-rw-r--r--res-xhdpi/images/loop00045.pngbin0 -> 14868 bytes
-rw-r--r--res-xhdpi/images/loop00046.pngbin0 -> 15135 bytes
-rw-r--r--res-xhdpi/images/loop00047.pngbin0 -> 14967 bytes
-rw-r--r--res-xhdpi/images/loop00048.pngbin0 -> 15144 bytes
-rw-r--r--res-xhdpi/images/loop00049.pngbin0 -> 15063 bytes
-rw-r--r--res-xhdpi/images/loop00050.pngbin0 -> 14846 bytes
-rw-r--r--res-xhdpi/images/loop00051.pngbin0 -> 14867 bytes
-rw-r--r--res-xhdpi/images/loop00052.pngbin0 -> 14738 bytes
-rw-r--r--res-xhdpi/images/loop00053.pngbin0 -> 14750 bytes
-rw-r--r--res-xhdpi/images/loop00054.pngbin0 -> 14430 bytes
-rw-r--r--res-xhdpi/images/loop00055.pngbin0 -> 14483 bytes
-rw-r--r--res-xhdpi/images/loop00056.pngbin0 -> 14106 bytes
-rw-r--r--res-xhdpi/images/loop00057.pngbin0 -> 14331 bytes
-rw-r--r--res-xhdpi/images/loop00058.pngbin0 -> 13771 bytes
-rw-r--r--res-xhdpi/images/loop00059.pngbin0 -> 13765 bytes
-rw-r--r--res-xhdpi/images/loop00060.pngbin0 -> 13502 bytes
-rw-r--r--res-xhdpi/images/loop00061.pngbin0 -> 13758 bytes
-rw-r--r--res-xhdpi/images/loop00062.pngbin0 -> 13659 bytes
-rw-r--r--res-xhdpi/images/loop00063.pngbin0 -> 13836 bytes
-rw-r--r--res-xhdpi/images/loop00064.pngbin0 -> 13734 bytes
-rw-r--r--res-xhdpi/images/loop00065.pngbin0 -> 13620 bytes
-rw-r--r--res-xhdpi/images/loop00066.pngbin0 -> 13530 bytes
-rw-r--r--res-xhdpi/images/loop00067.pngbin0 -> 13549 bytes
-rw-r--r--res-xhdpi/images/loop00068.pngbin0 -> 13608 bytes
-rw-r--r--res-xhdpi/images/loop00069.pngbin0 -> 13454 bytes
-rw-r--r--res-xhdpi/images/loop00070.pngbin0 -> 13830 bytes
-rw-r--r--res-xhdpi/images/loop00071.pngbin0 -> 13616 bytes
-rw-r--r--res-xhdpi/images/loop00072.pngbin0 -> 13308 bytes
-rw-r--r--res-xhdpi/images/loop00073.pngbin0 -> 13150 bytes
-rw-r--r--res-xhdpi/images/loop00074.pngbin0 -> 13091 bytes
-rw-r--r--res-xhdpi/images/loop00075.pngbin0 -> 12954 bytes
-rw-r--r--res-xhdpi/images/loop00076.pngbin0 -> 12621 bytes
-rw-r--r--res-xhdpi/images/loop00077.pngbin0 -> 12465 bytes
-rw-r--r--res-xhdpi/images/loop00078.pngbin0 -> 12583 bytes
-rw-r--r--res-xhdpi/images/loop00079.pngbin0 -> 12643 bytes
-rw-r--r--res-xhdpi/images/loop00080.pngbin0 -> 12859 bytes
-rw-r--r--res-xhdpi/images/loop00081.pngbin0 -> 13182 bytes
-rw-r--r--res-xhdpi/images/loop00082.pngbin0 -> 13031 bytes
-rw-r--r--res-xhdpi/images/loop00083.pngbin0 -> 12974 bytes
-rw-r--r--res-xhdpi/images/loop00084.pngbin0 -> 13116 bytes
-rw-r--r--res-xhdpi/images/loop00085.pngbin0 -> 13734 bytes
-rw-r--r--res-xhdpi/images/loop00086.pngbin0 -> 13390 bytes
-rw-r--r--res-xhdpi/images/loop00087.pngbin0 -> 13576 bytes
-rw-r--r--res-xhdpi/images/loop00088.pngbin0 -> 13439 bytes
-rw-r--r--res-xhdpi/images/loop00089.pngbin0 -> 13377 bytes
-rw-r--r--res-xhdpi/images/loop00090.pngbin0 -> 13121 bytes
-rw-r--r--res-xhdpi/images/no_command_text.pngbin37222 -> 94944 bytes
-rw-r--r--res-xhdpi/images/progress_empty.pngbin118 -> 113 bytes
-rw-r--r--res-xhdpi/images/progress_fill.pngbin404 -> 113 bytes
-rw-r--r--res-xxhdpi/images/erasing_text.pngbin52598 -> 136033 bytes
-rw-r--r--res-xxhdpi/images/error_text.pngbin27839 -> 96714 bytes
-rw-r--r--res-xxhdpi/images/icon_installing.pngbin129975 -> 0 bytes
-rw-r--r--res-xxhdpi/images/installing_security_text.pngbin0 -> 484913 bytes
-rw-r--r--res-xxhdpi/images/installing_text.pngbin133331 -> 455797 bytes
-rw-r--r--res-xxhdpi/images/loop00000.pngbin0 -> 23844 bytes
-rw-r--r--res-xxhdpi/images/loop00001.pngbin0 -> 23888 bytes
-rw-r--r--res-xxhdpi/images/loop00002.pngbin0 -> 23921 bytes
-rw-r--r--res-xxhdpi/images/loop00003.pngbin0 -> 23643 bytes
-rw-r--r--res-xxhdpi/images/loop00004.pngbin0 -> 24601 bytes
-rw-r--r--res-xxhdpi/images/loop00005.pngbin0 -> 24930 bytes
-rw-r--r--res-xxhdpi/images/loop00006.pngbin0 -> 25409 bytes
-rw-r--r--res-xxhdpi/images/loop00007.pngbin0 -> 25252 bytes
-rw-r--r--res-xxhdpi/images/loop00008.pngbin0 -> 25374 bytes
-rw-r--r--res-xxhdpi/images/loop00009.pngbin0 -> 25053 bytes
-rw-r--r--res-xxhdpi/images/loop00010.pngbin0 -> 25072 bytes
-rw-r--r--res-xxhdpi/images/loop00011.pngbin0 -> 25067 bytes
-rw-r--r--res-xxhdpi/images/loop00012.pngbin0 -> 24800 bytes
-rw-r--r--res-xxhdpi/images/loop00013.pngbin0 -> 24816 bytes
-rw-r--r--res-xxhdpi/images/loop00014.pngbin0 -> 24964 bytes
-rw-r--r--res-xxhdpi/images/loop00015.pngbin0 -> 25074 bytes
-rw-r--r--res-xxhdpi/images/loop00016.pngbin0 -> 25015 bytes
-rw-r--r--res-xxhdpi/images/loop00017.pngbin0 -> 25105 bytes
-rw-r--r--res-xxhdpi/images/loop00018.pngbin0 -> 25231 bytes
-rw-r--r--res-xxhdpi/images/loop00019.pngbin0 -> 24874 bytes
-rw-r--r--res-xxhdpi/images/loop00020.pngbin0 -> 24930 bytes
-rw-r--r--res-xxhdpi/images/loop00021.pngbin0 -> 24971 bytes
-rw-r--r--res-xxhdpi/images/loop00022.pngbin0 -> 25078 bytes
-rw-r--r--res-xxhdpi/images/loop00023.pngbin0 -> 24149 bytes
-rw-r--r--res-xxhdpi/images/loop00024.pngbin0 -> 24109 bytes
-rw-r--r--res-xxhdpi/images/loop00025.pngbin0 -> 23882 bytes
-rw-r--r--res-xxhdpi/images/loop00026.pngbin0 -> 24783 bytes
-rw-r--r--res-xxhdpi/images/loop00027.pngbin0 -> 24047 bytes
-rw-r--r--res-xxhdpi/images/loop00028.pngbin0 -> 24328 bytes
-rw-r--r--res-xxhdpi/images/loop00029.pngbin0 -> 24725 bytes
-rw-r--r--res-xxhdpi/images/loop00030.pngbin0 -> 24785 bytes
-rw-r--r--res-xxhdpi/images/loop00031.pngbin0 -> 24155 bytes
-rw-r--r--res-xxhdpi/images/loop00032.pngbin0 -> 25102 bytes
-rw-r--r--res-xxhdpi/images/loop00033.pngbin0 -> 24598 bytes
-rw-r--r--res-xxhdpi/images/loop00034.pngbin0 -> 24534 bytes
-rw-r--r--res-xxhdpi/images/loop00035.pngbin0 -> 25207 bytes
-rw-r--r--res-xxhdpi/images/loop00036.pngbin0 -> 24850 bytes
-rw-r--r--res-xxhdpi/images/loop00037.pngbin0 -> 25157 bytes
-rw-r--r--res-xxhdpi/images/loop00038.pngbin0 -> 25568 bytes
-rw-r--r--res-xxhdpi/images/loop00039.pngbin0 -> 25564 bytes
-rw-r--r--res-xxhdpi/images/loop00040.pngbin0 -> 26059 bytes
-rw-r--r--res-xxhdpi/images/loop00041.pngbin0 -> 25794 bytes
-rw-r--r--res-xxhdpi/images/loop00042.pngbin0 -> 26273 bytes
-rw-r--r--res-xxhdpi/images/loop00043.pngbin0 -> 25908 bytes
-rw-r--r--res-xxhdpi/images/loop00044.pngbin0 -> 26792 bytes
-rw-r--r--res-xxhdpi/images/loop00045.pngbin0 -> 26875 bytes
-rw-r--r--res-xxhdpi/images/loop00046.pngbin0 -> 26449 bytes
-rw-r--r--res-xxhdpi/images/loop00047.pngbin0 -> 27025 bytes
-rw-r--r--res-xxhdpi/images/loop00048.pngbin0 -> 27182 bytes
-rw-r--r--res-xxhdpi/images/loop00049.pngbin0 -> 27526 bytes
-rw-r--r--res-xxhdpi/images/loop00050.pngbin0 -> 25743 bytes
-rw-r--r--res-xxhdpi/images/loop00051.pngbin0 -> 26020 bytes
-rw-r--r--res-xxhdpi/images/loop00052.pngbin0 -> 26003 bytes
-rw-r--r--res-xxhdpi/images/loop00053.pngbin0 -> 25282 bytes
-rw-r--r--res-xxhdpi/images/loop00054.pngbin0 -> 25708 bytes
-rw-r--r--res-xxhdpi/images/loop00055.pngbin0 -> 25423 bytes
-rw-r--r--res-xxhdpi/images/loop00056.pngbin0 -> 25506 bytes
-rw-r--r--res-xxhdpi/images/loop00057.pngbin0 -> 25419 bytes
-rw-r--r--res-xxhdpi/images/loop00058.pngbin0 -> 24999 bytes
-rw-r--r--res-xxhdpi/images/loop00059.pngbin0 -> 24117 bytes
-rw-r--r--res-xxhdpi/images/loop00060.pngbin0 -> 24146 bytes
-rw-r--r--res-xxhdpi/images/loop00061.pngbin0 -> 24194 bytes
-rw-r--r--res-xxhdpi/images/loop00062.pngbin0 -> 24219 bytes
-rw-r--r--res-xxhdpi/images/loop00063.pngbin0 -> 24330 bytes
-rw-r--r--res-xxhdpi/images/loop00064.pngbin0 -> 24550 bytes
-rw-r--r--res-xxhdpi/images/loop00065.pngbin0 -> 24535 bytes
-rw-r--r--res-xxhdpi/images/loop00066.pngbin0 -> 24626 bytes
-rw-r--r--res-xxhdpi/images/loop00067.pngbin0 -> 24133 bytes
-rw-r--r--res-xxhdpi/images/loop00068.pngbin0 -> 24107 bytes
-rw-r--r--res-xxhdpi/images/loop00069.pngbin0 -> 24891 bytes
-rw-r--r--res-xxhdpi/images/loop00070.pngbin0 -> 24404 bytes
-rw-r--r--res-xxhdpi/images/loop00071.pngbin0 -> 24130 bytes
-rw-r--r--res-xxhdpi/images/loop00072.pngbin0 -> 24004 bytes
-rw-r--r--res-xxhdpi/images/loop00073.pngbin0 -> 23694 bytes
-rw-r--r--res-xxhdpi/images/loop00074.pngbin0 -> 23131 bytes
-rw-r--r--res-xxhdpi/images/loop00075.pngbin0 -> 23422 bytes
-rw-r--r--res-xxhdpi/images/loop00076.pngbin0 -> 22994 bytes
-rw-r--r--res-xxhdpi/images/loop00077.pngbin0 -> 23012 bytes
-rw-r--r--res-xxhdpi/images/loop00078.pngbin0 -> 22839 bytes
-rw-r--r--res-xxhdpi/images/loop00079.pngbin0 -> 23360 bytes
-rw-r--r--res-xxhdpi/images/loop00080.pngbin0 -> 23761 bytes
-rw-r--r--res-xxhdpi/images/loop00081.pngbin0 -> 23512 bytes
-rw-r--r--res-xxhdpi/images/loop00082.pngbin0 -> 23673 bytes
-rw-r--r--res-xxhdpi/images/loop00083.pngbin0 -> 24356 bytes
-rw-r--r--res-xxhdpi/images/loop00084.pngbin0 -> 23987 bytes
-rw-r--r--res-xxhdpi/images/loop00085.pngbin0 -> 24223 bytes
-rw-r--r--res-xxhdpi/images/loop00086.pngbin0 -> 24309 bytes
-rw-r--r--res-xxhdpi/images/loop00087.pngbin0 -> 24488 bytes
-rw-r--r--res-xxhdpi/images/loop00088.pngbin0 -> 24539 bytes
-rw-r--r--res-xxhdpi/images/loop00089.pngbin0 -> 24543 bytes
-rw-r--r--res-xxhdpi/images/loop00090.pngbin0 -> 23844 bytes
-rw-r--r--res-xxhdpi/images/no_command_text.pngbin63887 -> 266239 bytes
-rw-r--r--res-xxhdpi/images/progress_empty.pngbin118 -> 113 bytes
-rw-r--r--res-xxhdpi/images/progress_fill.pngbin404 -> 113 bytes
-rw-r--r--res-xxxhdpi/images/erasing_text.pngbin85500 -> 297262 bytes
-rw-r--r--res-xxxhdpi/images/error_text.pngbin40216 -> 199691 bytes
-rw-r--r--res-xxxhdpi/images/icon_installing.pngbin129975 -> 0 bytes
-rw-r--r--res-xxxhdpi/images/installing_security_text.pngbin0 -> 676381 bytes
-rw-r--r--res-xxxhdpi/images/installing_text.pngbin184958 -> 637038 bytes
-rw-r--r--res-xxxhdpi/images/loop00000.pngbin0 -> 32138 bytes
-rw-r--r--res-xxxhdpi/images/loop00001.pngbin0 -> 32195 bytes
-rw-r--r--res-xxxhdpi/images/loop00002.pngbin0 -> 32040 bytes
-rw-r--r--res-xxxhdpi/images/loop00003.pngbin0 -> 32554 bytes
-rw-r--r--res-xxxhdpi/images/loop00004.pngbin0 -> 32935 bytes
-rw-r--r--res-xxxhdpi/images/loop00005.pngbin0 -> 33131 bytes
-rw-r--r--res-xxxhdpi/images/loop00006.pngbin0 -> 33508 bytes
-rw-r--r--res-xxxhdpi/images/loop00007.pngbin0 -> 34862 bytes
-rw-r--r--res-xxxhdpi/images/loop00008.pngbin0 -> 34026 bytes
-rw-r--r--res-xxxhdpi/images/loop00009.pngbin0 -> 33660 bytes
-rw-r--r--res-xxxhdpi/images/loop00010.pngbin0 -> 34391 bytes
-rw-r--r--res-xxxhdpi/images/loop00011.pngbin0 -> 34154 bytes
-rw-r--r--res-xxxhdpi/images/loop00012.pngbin0 -> 34256 bytes
-rw-r--r--res-xxxhdpi/images/loop00013.pngbin0 -> 34040 bytes
-rw-r--r--res-xxxhdpi/images/loop00014.pngbin0 -> 35473 bytes
-rw-r--r--res-xxxhdpi/images/loop00015.pngbin0 -> 34333 bytes
-rw-r--r--res-xxxhdpi/images/loop00016.pngbin0 -> 33916 bytes
-rw-r--r--res-xxxhdpi/images/loop00017.pngbin0 -> 34493 bytes
-rw-r--r--res-xxxhdpi/images/loop00018.pngbin0 -> 33763 bytes
-rw-r--r--res-xxxhdpi/images/loop00019.pngbin0 -> 33855 bytes
-rw-r--r--res-xxxhdpi/images/loop00020.pngbin0 -> 33288 bytes
-rw-r--r--res-xxxhdpi/images/loop00021.pngbin0 -> 33174 bytes
-rw-r--r--res-xxxhdpi/images/loop00022.pngbin0 -> 33157 bytes
-rw-r--r--res-xxxhdpi/images/loop00023.pngbin0 -> 33287 bytes
-rw-r--r--res-xxxhdpi/images/loop00024.pngbin0 -> 32859 bytes
-rw-r--r--res-xxxhdpi/images/loop00025.pngbin0 -> 32260 bytes
-rw-r--r--res-xxxhdpi/images/loop00026.pngbin0 -> 32597 bytes
-rw-r--r--res-xxxhdpi/images/loop00027.pngbin0 -> 31878 bytes
-rw-r--r--res-xxxhdpi/images/loop00028.pngbin0 -> 32518 bytes
-rw-r--r--res-xxxhdpi/images/loop00029.pngbin0 -> 32930 bytes
-rw-r--r--res-xxxhdpi/images/loop00030.pngbin0 -> 33688 bytes
-rw-r--r--res-xxxhdpi/images/loop00031.pngbin0 -> 32547 bytes
-rw-r--r--res-xxxhdpi/images/loop00032.pngbin0 -> 33104 bytes
-rw-r--r--res-xxxhdpi/images/loop00033.pngbin0 -> 32907 bytes
-rw-r--r--res-xxxhdpi/images/loop00034.pngbin0 -> 33611 bytes
-rw-r--r--res-xxxhdpi/images/loop00035.pngbin0 -> 33202 bytes
-rw-r--r--res-xxxhdpi/images/loop00036.pngbin0 -> 32973 bytes
-rw-r--r--res-xxxhdpi/images/loop00037.pngbin0 -> 33595 bytes
-rw-r--r--res-xxxhdpi/images/loop00038.pngbin0 -> 34809 bytes
-rw-r--r--res-xxxhdpi/images/loop00039.pngbin0 -> 34692 bytes
-rw-r--r--res-xxxhdpi/images/loop00040.pngbin0 -> 35484 bytes
-rw-r--r--res-xxxhdpi/images/loop00041.pngbin0 -> 35146 bytes
-rw-r--r--res-xxxhdpi/images/loop00042.pngbin0 -> 34815 bytes
-rw-r--r--res-xxxhdpi/images/loop00043.pngbin0 -> 35465 bytes
-rw-r--r--res-xxxhdpi/images/loop00044.pngbin0 -> 35643 bytes
-rw-r--r--res-xxxhdpi/images/loop00045.pngbin0 -> 35835 bytes
-rw-r--r--res-xxxhdpi/images/loop00046.pngbin0 -> 36635 bytes
-rw-r--r--res-xxxhdpi/images/loop00047.pngbin0 -> 36481 bytes
-rw-r--r--res-xxxhdpi/images/loop00048.pngbin0 -> 36482 bytes
-rw-r--r--res-xxxhdpi/images/loop00049.pngbin0 -> 36341 bytes
-rw-r--r--res-xxxhdpi/images/loop00050.pngbin0 -> 34835 bytes
-rw-r--r--res-xxxhdpi/images/loop00051.pngbin0 -> 35569 bytes
-rw-r--r--res-xxxhdpi/images/loop00052.pngbin0 -> 34899 bytes
-rw-r--r--res-xxxhdpi/images/loop00053.pngbin0 -> 34589 bytes
-rw-r--r--res-xxxhdpi/images/loop00054.pngbin0 -> 34365 bytes
-rw-r--r--res-xxxhdpi/images/loop00055.pngbin0 -> 34332 bytes
-rw-r--r--res-xxxhdpi/images/loop00056.pngbin0 -> 34188 bytes
-rw-r--r--res-xxxhdpi/images/loop00057.pngbin0 -> 33961 bytes
-rw-r--r--res-xxxhdpi/images/loop00058.pngbin0 -> 33300 bytes
-rw-r--r--res-xxxhdpi/images/loop00059.pngbin0 -> 33405 bytes
-rw-r--r--res-xxxhdpi/images/loop00060.pngbin0 -> 33229 bytes
-rw-r--r--res-xxxhdpi/images/loop00061.pngbin0 -> 31814 bytes
-rw-r--r--res-xxxhdpi/images/loop00062.pngbin0 -> 32900 bytes
-rw-r--r--res-xxxhdpi/images/loop00063.pngbin0 -> 32809 bytes
-rw-r--r--res-xxxhdpi/images/loop00064.pngbin0 -> 32625 bytes
-rw-r--r--res-xxxhdpi/images/loop00065.pngbin0 -> 33560 bytes
-rw-r--r--res-xxxhdpi/images/loop00066.pngbin0 -> 32825 bytes
-rw-r--r--res-xxxhdpi/images/loop00067.pngbin0 -> 32885 bytes
-rw-r--r--res-xxxhdpi/images/loop00068.pngbin0 -> 31901 bytes
-rw-r--r--res-xxxhdpi/images/loop00069.pngbin0 -> 32514 bytes
-rw-r--r--res-xxxhdpi/images/loop00070.pngbin0 -> 33063 bytes
-rw-r--r--res-xxxhdpi/images/loop00071.pngbin0 -> 32486 bytes
-rw-r--r--res-xxxhdpi/images/loop00072.pngbin0 -> 32218 bytes
-rw-r--r--res-xxxhdpi/images/loop00073.pngbin0 -> 32100 bytes
-rw-r--r--res-xxxhdpi/images/loop00074.pngbin0 -> 31018 bytes
-rw-r--r--res-xxxhdpi/images/loop00075.pngbin0 -> 31186 bytes
-rw-r--r--res-xxxhdpi/images/loop00076.pngbin0 -> 30704 bytes
-rw-r--r--res-xxxhdpi/images/loop00077.pngbin0 -> 30379 bytes
-rw-r--r--res-xxxhdpi/images/loop00078.pngbin0 -> 31001 bytes
-rw-r--r--res-xxxhdpi/images/loop00079.pngbin0 -> 31273 bytes
-rw-r--r--res-xxxhdpi/images/loop00080.pngbin0 -> 30904 bytes
-rw-r--r--res-xxxhdpi/images/loop00081.pngbin0 -> 31821 bytes
-rw-r--r--res-xxxhdpi/images/loop00082.pngbin0 -> 31287 bytes
-rw-r--r--res-xxxhdpi/images/loop00083.pngbin0 -> 31149 bytes
-rw-r--r--res-xxxhdpi/images/loop00084.pngbin0 -> 31294 bytes
-rw-r--r--res-xxxhdpi/images/loop00085.pngbin0 -> 31875 bytes
-rw-r--r--res-xxxhdpi/images/loop00086.pngbin0 -> 32357 bytes
-rw-r--r--res-xxxhdpi/images/loop00087.pngbin0 -> 32312 bytes
-rw-r--r--res-xxxhdpi/images/loop00088.pngbin0 -> 31914 bytes
-rw-r--r--res-xxxhdpi/images/loop00089.pngbin0 -> 32685 bytes
-rw-r--r--res-xxxhdpi/images/loop00090.pngbin0 -> 32138 bytes
-rw-r--r--res-xxxhdpi/images/no_command_text.pngbin109746 -> 372530 bytes
-rw-r--r--res-xxxhdpi/images/progress_empty.pngbin118 -> 113 bytes
-rw-r--r--res-xxxhdpi/images/progress_fill.pngbin404 -> 113 bytes
-rw-r--r--roots.cpp8
-rw-r--r--roots.h6
-rw-r--r--screen_ui.cpp289
-rw-r--r--screen_ui.h64
-rw-r--r--tests/Android.mk16
-rw-r--r--tests/common/test_constants.h25
-rw-r--r--tests/component/applypatch_test.cpp392
-rw-r--r--tests/component/verifier_test.cpp8
-rw-r--r--tests/testdata/new.filebin0 -> 1388877 bytes
-rw-r--r--tests/testdata/old.filebin0 -> 1348051 bytes
-rw-r--r--tests/testdata/patch.bsdiffbin0 -> 57476 bytes
-rw-r--r--tests/unit/locale_test.cpp29
-rw-r--r--tools/recovery_l10n/res/layout/main.xml4
-rw-r--r--tools/recovery_l10n/res/values/strings.xml8
-rw-r--r--tools/recovery_l10n/src/com/android/recovery_l10n/Main.java9
-rw-r--r--ui.h1
-rw-r--r--uncrypt/Android.mk12
-rw-r--r--uncrypt/bootloader_message_writer.cpp107
-rw-r--r--uncrypt/include/bootloader_message_writer.h35
-rw-r--r--uncrypt/uncrypt.cpp316
-rw-r--r--uncrypt/uncrypt.rc10
-rw-r--r--updater/blockimg.cpp96
-rw-r--r--updater/install.cpp128
-rw-r--r--updater/updater.cpp17
-rw-r--r--verifier.cpp27
-rw-r--r--wear_touch.cpp177
-rw-r--r--wear_touch.h58
-rw-r--r--wear_ui.cpp125
-rw-r--r--wear_ui.h21
543 files changed, 1858 insertions, 563 deletions
diff --git a/Android.mk b/Android.mk
index 95e806ff9..355f4d841 100644
--- a/Android.mk
+++ b/Android.mk
@@ -43,6 +43,7 @@ LOCAL_SRC_FILES := \
ui.cpp \
verifier.cpp \
wear_ui.cpp \
+ wear_touch.cpp \
LOCAL_MODULE := recovery
diff --git a/adb_install.cpp b/adb_install.cpp
index 4cfcb2ab8..4aed9d4b1 100644
--- a/adb_install.cpp
+++ b/adb_install.cpp
@@ -113,7 +113,7 @@ apply_from_adb(RecoveryUI* ui_, bool* wipe_cache, const char* install_file) {
break;
}
}
- result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false);
+ result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false, 0);
break;
}
diff --git a/device.cpp b/device.cpp
index fd1a9875b..2465b0778 100644
--- a/device.cpp
+++ b/device.cpp
@@ -25,6 +25,7 @@ static const char* MENU_ITEMS[] = {
"Wipe cache partition",
"Mount /system",
"View recovery logs",
+ "Run graphics test",
"Power off",
NULL
};
@@ -43,7 +44,8 @@ Device::BuiltinAction Device::InvokeMenuItem(int menu_position) {
case 5: return WIPE_CACHE;
case 6: return MOUNT_SYSTEM;
case 7: return VIEW_RECOVERY_LOGS;
- case 8: return SHUTDOWN;
+ case 8: return RUN_GRAPHICS_TEST;
+ case 9: return SHUTDOWN;
default: return NO_ACTION;
}
}
diff --git a/device.h b/device.h
index f74b6b047..5017782e6 100644
--- a/device.h
+++ b/device.h
@@ -68,6 +68,7 @@ class Device {
SHUTDOWN = 8,
VIEW_RECOVERY_LOGS = 9,
MOUNT_SYSTEM = 10,
+ RUN_GRAPHICS_TEST = 11,
};
// Return the list of menu items (an array of strings,
diff --git a/edify/Android.mk b/edify/Android.mk
index 038dec088..71cf7652a 100644
--- a/edify/Android.mk
+++ b/edify/Android.mk
@@ -22,6 +22,8 @@ LOCAL_YACCFLAGS := -v
LOCAL_CPPFLAGS += -Wno-unused-parameter
LOCAL_CPPFLAGS += -Wno-deprecated-register
LOCAL_CLANG := true
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
+LOCAL_STATIC_LIBRARIES += libbase
include $(BUILD_HOST_EXECUTABLE)
@@ -36,5 +38,7 @@ LOCAL_CPPFLAGS := -Wno-unused-parameter
LOCAL_CPPFLAGS += -Wno-deprecated-register
LOCAL_MODULE := libedify
LOCAL_CLANG := true
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
+LOCAL_STATIC_LIBRARIES += libbase
include $(BUILD_STATIC_LIBRARY)
diff --git a/edify/expr.cpp b/edify/expr.cpp
index c34342f76..ecb1bea1a 100644
--- a/edify/expr.cpp
+++ b/edify/expr.cpp
@@ -21,6 +21,11 @@
#include <stdarg.h>
#include <unistd.h>
+#include <string>
+
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
#include "expr.h"
// Functions should:
@@ -36,7 +41,7 @@ char* Evaluate(State* state, Expr* expr) {
Value* v = expr->fn(expr->name, state, expr->argc, expr->argv);
if (v == NULL) return NULL;
if (v->type != VAL_STRING) {
- ErrorAbort(state, "expecting string, got value type %d", v->type);
+ ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
FreeValue(v);
return NULL;
}
@@ -494,15 +499,29 @@ Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
return args;
}
+static void ErrorAbortV(State* state, const char* format, va_list ap) {
+ std::string buffer;
+ android::base::StringAppendV(&buffer, format, ap);
+ free(state->errmsg);
+ state->errmsg = strdup(buffer.c_str());
+ return;
+}
+
// Use printf-style arguments to compose an error message to put into
-// *state. Returns NULL.
+// *state. Returns nullptr.
Value* ErrorAbort(State* state, const char* format, ...) {
- char* buffer = reinterpret_cast<char*>(malloc(4096));
- va_list v;
- va_start(v, format);
- vsnprintf(buffer, 4096, format, v);
- va_end(v);
- free(state->errmsg);
- state->errmsg = buffer;
- return NULL;
+ va_list ap;
+ va_start(ap, format);
+ ErrorAbortV(state, format, ap);
+ va_end(ap);
+ return nullptr;
+}
+
+Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ ErrorAbortV(state, format, ap);
+ va_end(ap);
+ state->cause_code = cause_code;
+ return nullptr;
}
diff --git a/edify/expr.h b/edify/expr.h
index 36f8e9612..5c06de846 100644
--- a/edify/expr.h
+++ b/edify/expr.h
@@ -19,6 +19,7 @@
#include <unistd.h>
+#include "error_code.h"
#include "yydefs.h"
#define MAX_STRING_LEN 1024
@@ -39,6 +40,15 @@ typedef struct {
// Should be NULL initially, will be either NULL or a malloc'd
// pointer after Evaluate() returns.
char* errmsg;
+
+ // error code indicates the type of failure (e.g. failure to update system image)
+ // during the OTA process.
+ ErrorCode error_code = kNoError;
+
+ // cause code provides more detailed reason of an OTA failure (e.g. fsync error)
+ // in addition to the error code.
+ CauseCode cause_code = kNoCause;
+
} State;
#define VAL_STRING 1 // data will be NULL-terminated; size doesn't count null
@@ -152,7 +162,13 @@ Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]);
// Use printf-style arguments to compose an error message to put into
// *state. Returns NULL.
-Value* ErrorAbort(State* state, const char* format, ...) __attribute__((format(printf, 2, 3)));
+Value* ErrorAbort(State* state, const char* format, ...)
+ __attribute__((format(printf, 2, 3), deprecated));
+
+// ErrorAbort has an optional (but recommended) argument 'cause_code'. If the cause code
+// is set, it will be logged into last_install and provides reason of OTA failures.
+Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...)
+ __attribute__((format(printf, 3, 4)));
// Wrap a string into a Value, taking ownership of the string.
Value* StringValue(char* str);
diff --git a/error_code.h b/error_code.h
new file mode 100644
index 000000000..259319ab4
--- /dev/null
+++ b/error_code.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef _ERROR_CODE_H_
+#define _ERROR_CODE_H_
+
+enum ErrorCode {
+ kNoError = -1,
+ kLowBattery = 20,
+ kZipVerificationFailure,
+ kZipOpenFailure
+};
+
+enum CauseCode {
+ kNoCause = -1,
+ kArgsParsingFailure = 100,
+ kStashCreationFailure,
+ kFileOpenFailure,
+ kLseekFailure,
+ kFreadFailure,
+ kFwriteFailure,
+ kFsyncFailure,
+ kLibfecFailure,
+ kFileGetPropFailure,
+ kFileRenameFailure,
+ kSymlinkFailure,
+ kSetMetadataFailure,
+ kTune2FsFailure,
+ kRebootFailure,
+ kVendorFailure = 200
+};
+
+#endif
diff --git a/install.cpp b/install.cpp
index a7b59c3e7..9d2971c8c 100644
--- a/install.cpp
+++ b/install.cpp
@@ -23,9 +23,15 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <chrono>
+#include <string>
#include <vector>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
#include "common.h"
+#include "error_code.h"
#include "install.h"
#include "minui/minui.h"
#include "minzip/SysUtil.h"
@@ -49,7 +55,9 @@ static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
// If the package contains an update binary, extract it and run it.
static int
-try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache) {
+try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache,
+ std::vector<std::string>& log_buffer)
+{
const ZipEntry* binary_entry =
mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
if (binary_entry == NULL) {
@@ -182,6 +190,10 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache) {
ui->SetEnableReboot(true);
} else if (strcmp(command, "retry_update") == 0) {
retry_update = true;
+ } else if (strcmp(command, "log") == 0) {
+ // Save the logging request from updater and write to
+ // last_install later.
+ log_buffer.push_back(std::string(strtok(NULL, "\n")));
} else {
LOGE("unknown command [%s]\n", command);
}
@@ -202,7 +214,8 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache) {
}
static int
-really_install_package(const char *path, bool* wipe_cache, bool needs_mount)
+really_install_package(const char *path, bool* wipe_cache, bool needs_mount,
+ std::vector<std::string>& log_buffer)
{
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
ui->Print("Finding update package...\n");
@@ -228,6 +241,7 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount)
return INSTALL_CORRUPT;
}
+ // Load keys.
std::vector<Certificate> loadedKeys;
if (!load_keys(PUBLIC_KEYS_FILE, loadedKeys)) {
LOGE("Failed to load keys\n");
@@ -235,31 +249,35 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount)
}
LOGI("%zu key(s) loaded from %s\n", loadedKeys.size(), PUBLIC_KEYS_FILE);
+ // Verify package.
ui->Print("Verifying update package...\n");
-
+ auto t0 = std::chrono::system_clock::now();
int err = verify_file(map.addr, map.length, loadedKeys);
- LOGI("verify_file returned %d\n", err);
+ std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0;
+ ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err);
if (err != VERIFY_SUCCESS) {
LOGE("signature verification failed\n");
+ log_buffer.push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
+
sysReleaseMap(&map);
return INSTALL_CORRUPT;
}
- /* Try to open the package.
- */
+ // Try to open the package.
ZipArchive zip;
err = mzOpenZipArchive(map.addr, map.length, &zip);
if (err != 0) {
LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
+ log_buffer.push_back(android::base::StringPrintf("error: %d", kZipOpenFailure));
+
sysReleaseMap(&map);
return INSTALL_CORRUPT;
}
- /* Verify and install the contents of the package.
- */
+ // Verify and install the contents of the package.
ui->Print("Installing update...\n");
ui->SetEnableReboot(false);
- int result = try_update_binary(path, &zip, wipe_cache);
+ int result = try_update_binary(path, &zip, wipe_cache, log_buffer);
ui->SetEnableReboot(true);
ui->Print("\n");
@@ -270,9 +288,10 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount)
int
install_package(const char* path, bool* wipe_cache, const char* install_file,
- bool needs_mount)
+ bool needs_mount, int retry_count)
{
modified_flash = true;
+ auto start = std::chrono::system_clock::now();
FILE* install_log = fopen_path(install_file, "w");
if (install_log) {
@@ -282,15 +301,26 @@ install_package(const char* path, bool* wipe_cache, const char* install_file,
LOGE("failed to open last_install: %s\n", strerror(errno));
}
int result;
+ std::vector<std::string> log_buffer;
if (setup_install_mounts() != 0) {
LOGE("failed to set up expected mounts for install; aborting\n");
result = INSTALL_ERROR;
} else {
- result = really_install_package(path, wipe_cache, needs_mount);
+ result = really_install_package(path, wipe_cache, needs_mount, log_buffer);
}
- if (install_log) {
+ if (install_log != nullptr) {
fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
fputc('\n', install_log);
+ std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
+ int count = static_cast<int>(duration.count());
+ // Report the time spent to apply OTA update in seconds.
+ fprintf(install_log, "time_total: %d\n", count);
+ fprintf(install_log, "retry: %d\n", retry_count);
+
+ for (const auto& s : log_buffer) {
+ fprintf(install_log, "%s\n", s.c_str());
+ }
+
fclose(install_log);
}
return result;
diff --git a/install.h b/install.h
index fd08e3c49..66764f542 100644
--- a/install.h
+++ b/install.h
@@ -28,8 +28,8 @@ enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE, INSTALL_SK
// Install the package specified by root_path. If INSTALL_SUCCESS is
// returned and *wipe_cache is true on exit, caller should wipe the
// cache partition.
-int install_package(const char* root_path, bool* wipe_cache,
- const char* install_file, bool needs_mount);
+int install_package(const char* root_path, bool* wipe_cache, const char* install_file,
+ bool needs_mount, int retry_count);
#ifdef __cplusplus
}
diff --git a/interlace-frames.py b/interlace-frames.py
index 3e777b470..6b435aa90 100644..100755
--- a/interlace-frames.py
+++ b/interlace-frames.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
# Copyright (C) 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,19 +14,16 @@
# limitations under the License.
"""
-Script to take a set of frames (PNG files) for a recovery animation and turn
-it into a single output image which contains the input frames interlaced by
-row. Run with the names of all the input frames on the command line. Specify
-the name of the output file with -o (or --output), and optionally specify the
-number of frames per second (FPS) with --fps (default: 20).
-
-e.g.
-interlace-frames.py --fps 20 --output output.png frame0.png frame1.png frame3.png
+Script to take a set of frames (PNG files) for a recovery animation
+and turn it into a single output image which contains the input frames
+interlaced by row. Run with the names of all the input frames on the
+command line, in order, followed by the name of the output file.
"""
from __future__ import print_function
import argparse
+import os.path
import sys
try:
import Image
@@ -35,7 +33,7 @@ except ImportError:
sys.exit(1)
-def interlace(output, fps, inputs):
+def interlace(output, inputs):
frames = [Image.open(fn).convert("RGB") for fn in inputs]
assert len(frames) > 0, "Must have at least one input frame."
sizes = set()
@@ -60,21 +58,57 @@ def interlace(output, fps, inputs):
meta = PngImagePlugin.PngInfo()
meta.add_text("Frames", str(N))
- meta.add_text("FPS", str(fps))
out.save(output, pnginfo=meta)
+def deinterlace(output, input):
+ # Truncate the output filename extension if it's '.png'.
+ if os.path.splitext(output)[1].lower() == '.png':
+ output = output[:-4]
+
+ img2 = Image.open(input)
+ print(img2.mode)
+ palette = img2.getpalette()
+ img = img2.convert("RGB")
+ num_frames = int(img.info.get('Frames', 1))
+ print('Found %d frames in %s.' % (num_frames, input))
+ assert num_frames > 0, 'Invalid Frames meta.'
+
+ # palette = img.getpalette()
+ print(palette)
+
+ width, height = img.size
+ height /= num_frames
+ for k in range(num_frames):
+ out = Image.new('RGB', (width, height))
+ out.info = img.info
+ for i in range(width):
+ for j in range(height):
+ out.putpixel((i, j), img.getpixel((i, j * num_frames + k)))
+ # out.putpalette(img.getpalette(), rawmode='RGB')
+ out2 = out.convert(mode='P', palette=palette)
+ #out2 = out
+ print(out2.mode)
+ # out2.putpalette(palette)
+ filename = '%s%02d.png' % (output, k)
+ out2.save(filename)
+ print('Frame %d written to %s.' % (k, filename))
+
+
def main(argv):
- parser = argparse.ArgumentParser()
- parser.add_argument('--fps', default=20)
+ parser = argparse.ArgumentParser(description='Parse')
+ parser.add_argument('--deinterlace', '-d', action='store_true')
parser.add_argument('--output', '-o', required=True)
parser.add_argument('input', nargs='+')
args = parser.parse_args(argv)
- interlace(args.output, args.fps, args.input)
+ if args.deinterlace:
+ # args.input is a list, and we only process the first when deinterlacing.
+ deinterlace(args.output, args.input[0])
+ else:
+ interlace(args.output, args.input)
if __name__ == '__main__':
main(sys.argv[1:])
-
diff --git a/minui/minui.h b/minui/minui.h
index e3bc00548..fb0bbe10c 100644
--- a/minui/minui.h
+++ b/minui/minui.h
@@ -84,6 +84,8 @@ int ev_get_epollfd();
// Resources
//
+bool matches_locale(const char* prefix, const char* locale);
+
// res_create_*_surface() functions return 0 if no error, else
// negative.
//
diff --git a/minui/resources.cpp b/minui/resources.cpp
index 8489d60ef..730b05f13 100644
--- a/minui/resources.cpp
+++ b/minui/resources.cpp
@@ -33,8 +33,6 @@
#include "minui.h"
-extern char* locale;
-
#define SURFACE_DATA_ALIGNMENT 8
static GRSurface* malloc_surface(size_t data_size) {
@@ -373,21 +371,16 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface) {
return result;
}
-static int matches_locale(const char* loc, const char* locale) {
- if (locale == NULL) return 0;
-
- if (strcmp(loc, locale) == 0) return 1;
-
- // if loc does *not* have an underscore, and it matches the start
- // of locale, and the next character in locale *is* an underscore,
- // that's a match. For instance, loc == "en" matches locale ==
- // "en_US".
+// This function tests if a locale string stored in PNG (prefix) matches
+// the locale string provided by the system (locale).
+bool matches_locale(const char* prefix, const char* locale) {
+ if (locale == NULL) return false;
- int i;
- for (i = 0; loc[i] != 0 && loc[i] != '_'; ++i);
- if (loc[i] == '_') return 0;
+ // Return true if the whole string of prefix matches the top part of
+ // locale. For instance, prefix == "en" matches locale == "en_US";
+ // and prefix == "zh_CN" matches locale == "zh_CN_#Hans".
- return (strncmp(locale, loc, i) == 0 && locale[i] == '_');
+ return (strncmp(prefix, locale, strlen(prefix)) == 0);
}
int res_create_localized_alpha_surface(const char* name,
diff --git a/minzip/SysUtil.c b/minzip/SysUtil.c
index 09ec8768f..e7dd17b51 100644
--- a/minzip/SysUtil.c
+++ b/minzip/SysUtil.c
@@ -39,6 +39,11 @@ static bool sysMapFD(int fd, MemMapping* pMap) {
pMap->length = sb.st_size;
pMap->range_count = 1;
pMap->ranges = malloc(sizeof(MappedRange));
+ if (pMap->ranges == NULL) {
+ LOGE("malloc failed: %s\n", strerror(errno));
+ munmap(memPtr, sb.st_size);
+ return false;
+ }
pMap->ranges[0].addr = memPtr;
pMap->ranges[0].length = sb.st_size;
@@ -50,7 +55,7 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap)
char block_dev[PATH_MAX+1];
size_t size;
unsigned int blksize;
- unsigned int blocks;
+ size_t blocks;
unsigned int range_count;
unsigned int i;
@@ -69,49 +74,80 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap)
LOGE("failed to parse block map header\n");
return -1;
}
-
- blocks = ((size-1) / blksize) + 1;
+ if (blksize != 0) {
+ blocks = ((size-1) / blksize) + 1;
+ }
+ if (size == 0 || blksize == 0 || blocks > SIZE_MAX / blksize || range_count == 0) {
+ LOGE("invalid data in block map file: size %zu, blksize %u, range_count %u\n",
+ size, blksize, range_count);
+ return -1;
+ }
pMap->range_count = range_count;
- pMap->ranges = malloc(range_count * sizeof(MappedRange));
- memset(pMap->ranges, 0, range_count * sizeof(MappedRange));
+ pMap->ranges = calloc(range_count, sizeof(MappedRange));
+ if (pMap->ranges == NULL) {
+ LOGE("calloc(%u, %zu) failed: %s\n", range_count, sizeof(MappedRange), strerror(errno));
+ return -1;
+ }
// Reserve enough contiguous address space for the whole file.
unsigned char* reserve;
reserve = mmap64(NULL, blocks * blksize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
if (reserve == MAP_FAILED) {
LOGE("failed to reserve address space: %s\n", strerror(errno));
+ free(pMap->ranges);
return -1;
}
- pMap->ranges[range_count-1].addr = reserve;
- pMap->ranges[range_count-1].length = blocks * blksize;
-
int fd = open(block_dev, O_RDONLY);
if (fd < 0) {
LOGE("failed to open block device %s: %s\n", block_dev, strerror(errno));
+ munmap(reserve, blocks * blksize);
+ free(pMap->ranges);
return -1;
}
unsigned char* next = reserve;
+ size_t remaining_size = blocks * blksize;
+ bool success = true;
for (i = 0; i < range_count; ++i) {
- int start, end;
- if (fscanf(mapf, "%d %d\n", &start, &end) != 2) {
+ size_t start, end;
+ if (fscanf(mapf, "%zu %zu\n", &start, &end) != 2) {
LOGE("failed to parse range %d in block map\n", i);
- return -1;
+ success = false;
+ break;
+ }
+ size_t length = (end - start) * blksize;
+ if (end <= start || (end - start) > SIZE_MAX / blksize || length > remaining_size) {
+ LOGE("unexpected range in block map: %zu %zu\n", start, end);
+ success = false;
+ break;
}
- void* addr = mmap64(next, (end-start)*blksize, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ((off64_t)start)*blksize);
+ void* addr = mmap64(next, length, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ((off64_t)start)*blksize);
if (addr == MAP_FAILED) {
LOGE("failed to map block %d: %s\n", i, strerror(errno));
- return -1;
+ success = false;
+ break;
}
pMap->ranges[i].addr = addr;
- pMap->ranges[i].length = (end-start)*blksize;
+ pMap->ranges[i].length = length;
- next += pMap->ranges[i].length;
+ next += length;
+ remaining_size -= length;
+ }
+ if (success && remaining_size != 0) {
+ LOGE("ranges in block map are invalid: remaining_size = %zu\n", remaining_size);
+ success = false;
+ }
+ if (!success) {
+ close(fd);
+ munmap(reserve, blocks * blksize);
+ free(pMap->ranges);
+ return -1;
}
+ close(fd);
pMap->addr = reserve;
pMap->length = size;
@@ -134,6 +170,7 @@ int sysMapFile(const char* fn, MemMapping* pMap)
if (sysMapBlockFile(mapf, pMap) != 0) {
LOGE("Map of '%s' failed\n", fn);
+ fclose(mapf);
return -1;
}
diff --git a/otafault/Android.mk b/otafault/Android.mk
index 50e385efb..d0b1174a4 100644
--- a/otafault/Android.mk
+++ b/otafault/Android.mk
@@ -14,8 +14,6 @@
LOCAL_PATH := $(call my-dir)
-# otafault (static library)
-# ===============================
include $(CLEAR_VARS)
otafault_static_libs := \
@@ -25,11 +23,12 @@ otafault_static_libs := \
libselinux
LOCAL_SRC_FILES := config.cpp ota_io.cpp
+LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := libotafault
LOCAL_CLANG := true
LOCAL_C_INCLUDES := bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_STATIC_LIBRARIES := $(otafault_static_libs)
+LOCAL_WHOLE_STATIC_LIBRARIES := $(otafault_static_libs)
include $(BUILD_STATIC_LIBRARY)
@@ -40,9 +39,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := config.cpp ota_io.cpp test.cpp
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE := otafault_test
-LOCAL_STATIC_LIBRARIES := \
- libotafault \
- $(otafault_static_libs)
+LOCAL_STATIC_LIBRARIES := $(otafault_static_libs)
LOCAL_C_INCLUDES := bootable/recovery
LOCAL_FORCE_STATIC_EXECUTABLE := true
diff --git a/otafault/ota_io.cpp b/otafault/ota_io.cpp
index dd805e56e..94be8155a 100644
--- a/otafault/ota_io.cpp
+++ b/otafault/ota_io.cpp
@@ -29,7 +29,6 @@ static std::map<intptr_t, const char*> filename_cache;
static std::string read_fault_file_name = "";
static std::string write_fault_file_name = "";
static std::string fsync_fault_file_name = "";
-bool have_eio_error = false;
static bool get_hit_file(const char* cached_path, std::string ffn) {
return should_hit_cache()
@@ -49,6 +48,8 @@ void ota_set_fault_files() {
}
}
+bool have_eio_error = false;
+
int ota_open(const char* path, int oflags) {
// Let the caller handle errors; we do not care if open succeeds or fails
int fd = open(path, oflags);
diff --git a/print_sha1.h b/print_sha1.h
index fa3d7e009..c7c1f3651 100644
--- a/print_sha1.h
+++ b/print_sha1.h
@@ -22,7 +22,7 @@
#include "openssl/sha.h"
-static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH], size_t len) {
+static std::string print_sha1(const uint8_t* sha1, size_t len) {
const char* hex = "0123456789abcdef";
std::string result = "";
for (size_t i = 0; i < len; ++i) {
@@ -40,4 +40,8 @@ static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) {
return print_sha1(sha1, 4);
}
+static std::string print_hex(const uint8_t* bytes, size_t len) {
+ return print_sha1(bytes, len);
+}
+
#endif // RECOVERY_PRINT_SHA1_H
diff --git a/recovery.cpp b/recovery.cpp
index 4a3c7ef1a..573ae1abb 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -51,6 +51,7 @@
#include "bootloader.h"
#include "common.h"
#include "device.h"
+#include "error_code.h"
#include "fuse_sdcard_provider.h"
#include "fuse_sideload.h"
#include "install.h"
@@ -75,6 +76,7 @@ static const struct option OPTIONS[] = {
{ "stages", required_argument, NULL, 'g' },
{ "shutdown_after", no_argument, NULL, 'p' },
{ "reason", required_argument, NULL, 'r' },
+ { "security", no_argument, NULL, 'e'},
{ NULL, 0, NULL, 0 },
};
@@ -83,7 +85,10 @@ static const char *COMMAND_FILE = "/cache/recovery/command";
static const char *LOG_FILE = "/cache/recovery/log";
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
static const char *LOCALE_FILE = "/cache/recovery/last_locale";
+static const char *CONVERT_FBE_DIR = "/tmp/convert_fbe";
+static const char *CONVERT_FBE_FILE = "/tmp/convert_fbe/convert_fbe";
static const char *CACHE_ROOT = "/cache";
+static const char *DATA_ROOT = "/data";
static const char *SDCARD_ROOT = "/sdcard";
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install";
@@ -99,7 +104,7 @@ static const int BATTERY_OK_PERCENTAGE = 20;
static const int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15;
RecoveryUI* ui = NULL;
-char* locale = NULL;
+static const char* locale = "en_US";
char* stage = NULL;
char* reason = NULL;
bool modified_flash = false;
@@ -530,6 +535,7 @@ typedef struct _saved_log_file {
static bool erase_volume(const char* volume) {
bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
+ bool is_data = (strcmp(volume, DATA_ROOT) == 0);
ui->SetBackground(RecoveryUI::ERASING);
ui->SetProgressType(RecoveryUI::INDETERMINATE);
@@ -584,7 +590,28 @@ static bool erase_volume(const char* volume) {
ui->Print("Formatting %s...\n", volume);
ensure_path_unmounted(volume);
- int result = format_volume(volume);
+
+ int result;
+
+ if (is_data && reason && strcmp(reason, "convert_fbe") == 0) {
+ // Create convert_fbe breadcrumb file to signal to init
+ // to convert to file based encryption, not full disk encryption
+ if (mkdir(CONVERT_FBE_DIR, 0700) != 0) {
+ ui->Print("Failed to make convert_fbe dir %s\n", strerror(errno));
+ return true;
+ }
+ FILE* f = fopen(CONVERT_FBE_FILE, "wb");
+ if (!f) {
+ ui->Print("Failed to convert to file encryption %s\n", strerror(errno));
+ return true;
+ }
+ fclose(f);
+ result = format_volume(volume, CONVERT_FBE_DIR);
+ remove(CONVERT_FBE_FILE);
+ rmdir(CONVERT_FBE_DIR);
+ } else {
+ result = format_volume(volume);
+ }
if (is_cache) {
while (head) {
@@ -870,6 +897,37 @@ static void choose_recovery_file(Device* device) {
}
}
+static void run_graphics_test(Device* device) {
+ // Switch to graphics screen.
+ ui->ShowText(false);
+
+ ui->SetProgressType(RecoveryUI::INDETERMINATE);
+ ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
+ sleep(1);
+
+ ui->SetBackground(RecoveryUI::ERROR);
+ sleep(1);
+
+ ui->SetBackground(RecoveryUI::NO_COMMAND);
+ sleep(1);
+
+ ui->SetBackground(RecoveryUI::ERASING);
+ sleep(1);
+
+ ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
+
+ ui->SetProgressType(RecoveryUI::DETERMINATE);
+ ui->ShowProgress(1.0, 10.0);
+ float fraction = 0.0;
+ for (size_t i = 0; i < 100; ++i) {
+ fraction += .01;
+ ui->SetProgress(fraction);
+ usleep(100000);
+ }
+
+ ui->ShowText(true);
+}
+
// How long (in seconds) we wait for the fuse-provided package file to
// appear, before timing out.
#define SDCARD_INSTALL_TIMEOUT 10
@@ -928,7 +986,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) {
}
result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache,
- TEMPORARY_INSTALL_FILE, false);
+ TEMPORARY_INSTALL_FILE, false, 0/*retry_count*/);
break;
}
@@ -1028,6 +1086,10 @@ prompt_and_wait(Device* device, int status) {
choose_recovery_file(device);
break;
+ case Device::RUN_GRAPHICS_TEST:
+ run_graphics_test(device);
+ break;
+
case Device::MOUNT_SYSTEM:
char system_root_image[PROPERTY_VALUE_MAX];
property_get("ro.build.system_root_image", system_root_image, "");
@@ -1268,6 +1330,7 @@ int main(int argc, char **argv) {
bool just_exit = false;
bool shutdown_after = false;
int retry_count = 0;
+ bool security_update = false;
int arg;
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
@@ -1291,6 +1354,7 @@ int main(int argc, char **argv) {
}
case 'p': shutdown_after = true; break;
case 'r': reason = optarg; break;
+ case 'e': security_update = true; break;
case '?':
LOGE("Invalid command argument\n");
continue;
@@ -1310,6 +1374,9 @@ int main(int argc, char **argv) {
ui->SetLocale(locale);
ui->Init();
+ // Set background string to "installing security update" for security update,
+ // otherwise set it to "installing system update".
+ ui->SetSystemUpdateText(security_update);
int st_cur, st_max;
if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) {
@@ -1372,10 +1439,21 @@ int main(int argc, char **argv) {
if (!is_battery_ok()) {
ui->Print("battery capacity is not enough for installing package, needed is %d%%\n",
BATTERY_OK_PERCENTAGE);
+ // Log the error code to last_install when installation skips due to
+ // low battery.
+ FILE* install_log = fopen_path(LAST_INSTALL_FILE, "w");
+ if (install_log != nullptr) {
+ fprintf(install_log, "%s\n", update_package);
+ fprintf(install_log, "0\n");
+ fprintf(install_log, "error: %d\n", kLowBattery);
+ fclose(install_log);
+ } else {
+ LOGE("failed to open last_install: %s\n", strerror(errno));
+ }
status = INSTALL_SKIPPED;
} else {
status = install_package(update_package, &should_wipe_cache,
- TEMPORARY_INSTALL_FILE, true);
+ TEMPORARY_INSTALL_FILE, true, retry_count);
if (status == INSTALL_SUCCESS && should_wipe_cache) {
wipe_cache(false, device);
}
diff --git a/res-560dpi b/res-560dpi
index 8576a9b95..1db3a2e23 120000
--- a/res-560dpi
+++ b/res-560dpi
@@ -1 +1 @@
-res-xxhdpi \ No newline at end of file
+res-xxxhdpi \ No newline at end of file
diff --git a/res-hdpi/images/erasing_text.png b/res-hdpi/images/erasing_text.png
index 774244c84..e500d0268 100644
--- a/res-hdpi/images/erasing_text.png
+++ b/res-hdpi/images/erasing_text.png
Binary files differ
diff --git a/res-hdpi/images/error_text.png b/res-hdpi/images/error_text.png
index 64a57ec4e..9a3597b82 100644
--- a/res-hdpi/images/error_text.png
+++ b/res-hdpi/images/error_text.png
Binary files differ
diff --git a/res-hdpi/images/icon_installing.png b/res-hdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc231..000000000
--- a/res-hdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-hdpi/images/installing_security_text.png b/res-hdpi/images/installing_security_text.png
new file mode 100644
index 000000000..76e747410
--- /dev/null
+++ b/res-hdpi/images/installing_security_text.png
Binary files differ
diff --git a/res-hdpi/images/installing_text.png b/res-hdpi/images/installing_text.png
index 33b54f1bf..5d2a5fa0c 100644
--- a/res-hdpi/images/installing_text.png
+++ b/res-hdpi/images/installing_text.png
Binary files differ
diff --git a/res-hdpi/images/loop00000.png b/res-hdpi/images/loop00000.png
new file mode 100644
index 000000000..030fa2b36
--- /dev/null
+++ b/res-hdpi/images/loop00000.png
Binary files differ
diff --git a/res-hdpi/images/loop00001.png b/res-hdpi/images/loop00001.png
new file mode 100644
index 000000000..546a10247
--- /dev/null
+++ b/res-hdpi/images/loop00001.png
Binary files differ
diff --git a/res-hdpi/images/loop00002.png b/res-hdpi/images/loop00002.png
new file mode 100644
index 000000000..262be3f24
--- /dev/null
+++ b/res-hdpi/images/loop00002.png
Binary files differ
diff --git a/res-hdpi/images/loop00003.png b/res-hdpi/images/loop00003.png
new file mode 100644
index 000000000..1282fb308
--- /dev/null
+++ b/res-hdpi/images/loop00003.png
Binary files differ
diff --git a/res-hdpi/images/loop00004.png b/res-hdpi/images/loop00004.png
new file mode 100644
index 000000000..2ff7678ff
--- /dev/null
+++ b/res-hdpi/images/loop00004.png
Binary files differ
diff --git a/res-hdpi/images/loop00005.png b/res-hdpi/images/loop00005.png
new file mode 100644
index 000000000..20b4d815b
--- /dev/null
+++ b/res-hdpi/images/loop00005.png
Binary files differ
diff --git a/res-hdpi/images/loop00006.png b/res-hdpi/images/loop00006.png
new file mode 100644
index 000000000..0f5b28d49
--- /dev/null
+++ b/res-hdpi/images/loop00006.png
Binary files differ
diff --git a/res-hdpi/images/loop00007.png b/res-hdpi/images/loop00007.png
new file mode 100644
index 000000000..008acc85b
--- /dev/null
+++ b/res-hdpi/images/loop00007.png
Binary files differ
diff --git a/res-hdpi/images/loop00008.png b/res-hdpi/images/loop00008.png
new file mode 100644
index 000000000..ca1309dc2
--- /dev/null
+++ b/res-hdpi/images/loop00008.png
Binary files differ
diff --git a/res-hdpi/images/loop00009.png b/res-hdpi/images/loop00009.png
new file mode 100644
index 000000000..b2730f198
--- /dev/null
+++ b/res-hdpi/images/loop00009.png
Binary files differ
diff --git a/res-hdpi/images/loop00010.png b/res-hdpi/images/loop00010.png
new file mode 100644
index 000000000..3867e9c96
--- /dev/null
+++ b/res-hdpi/images/loop00010.png
Binary files differ
diff --git a/res-hdpi/images/loop00011.png b/res-hdpi/images/loop00011.png
new file mode 100644
index 000000000..2761d8fcb
--- /dev/null
+++ b/res-hdpi/images/loop00011.png
Binary files differ
diff --git a/res-hdpi/images/loop00012.png b/res-hdpi/images/loop00012.png
new file mode 100644
index 000000000..2d976ef62
--- /dev/null
+++ b/res-hdpi/images/loop00012.png
Binary files differ
diff --git a/res-hdpi/images/loop00013.png b/res-hdpi/images/loop00013.png
new file mode 100644
index 000000000..5c96bb52c
--- /dev/null
+++ b/res-hdpi/images/loop00013.png
Binary files differ
diff --git a/res-hdpi/images/loop00014.png b/res-hdpi/images/loop00014.png
new file mode 100644
index 000000000..d481ec57a
--- /dev/null
+++ b/res-hdpi/images/loop00014.png
Binary files differ
diff --git a/res-hdpi/images/loop00015.png b/res-hdpi/images/loop00015.png
new file mode 100644
index 000000000..47716ede3
--- /dev/null
+++ b/res-hdpi/images/loop00015.png
Binary files differ
diff --git a/res-hdpi/images/loop00016.png b/res-hdpi/images/loop00016.png
new file mode 100644
index 000000000..c0cffe85c
--- /dev/null
+++ b/res-hdpi/images/loop00016.png
Binary files differ
diff --git a/res-hdpi/images/loop00017.png b/res-hdpi/images/loop00017.png
new file mode 100644
index 000000000..a0dc2e51f
--- /dev/null
+++ b/res-hdpi/images/loop00017.png
Binary files differ
diff --git a/res-hdpi/images/loop00018.png b/res-hdpi/images/loop00018.png
new file mode 100644
index 000000000..c8eefc5f8
--- /dev/null
+++ b/res-hdpi/images/loop00018.png
Binary files differ
diff --git a/res-hdpi/images/loop00019.png b/res-hdpi/images/loop00019.png
new file mode 100644
index 000000000..0d9d8e0fe
--- /dev/null
+++ b/res-hdpi/images/loop00019.png
Binary files differ
diff --git a/res-hdpi/images/loop00020.png b/res-hdpi/images/loop00020.png
new file mode 100644
index 000000000..b4909a80d
--- /dev/null
+++ b/res-hdpi/images/loop00020.png
Binary files differ
diff --git a/res-hdpi/images/loop00021.png b/res-hdpi/images/loop00021.png
new file mode 100644
index 000000000..b3c5274c8
--- /dev/null
+++ b/res-hdpi/images/loop00021.png
Binary files differ
diff --git a/res-hdpi/images/loop00022.png b/res-hdpi/images/loop00022.png
new file mode 100644
index 000000000..827c93707
--- /dev/null
+++ b/res-hdpi/images/loop00022.png
Binary files differ
diff --git a/res-hdpi/images/loop00023.png b/res-hdpi/images/loop00023.png
new file mode 100644
index 000000000..84440fec6
--- /dev/null
+++ b/res-hdpi/images/loop00023.png
Binary files differ
diff --git a/res-hdpi/images/loop00024.png b/res-hdpi/images/loop00024.png
new file mode 100644
index 000000000..cfc4c5bab
--- /dev/null
+++ b/res-hdpi/images/loop00024.png
Binary files differ
diff --git a/res-hdpi/images/loop00025.png b/res-hdpi/images/loop00025.png
new file mode 100644
index 000000000..fd048fdcf
--- /dev/null
+++ b/res-hdpi/images/loop00025.png
Binary files differ
diff --git a/res-hdpi/images/loop00026.png b/res-hdpi/images/loop00026.png
new file mode 100644
index 000000000..68251873a
--- /dev/null
+++ b/res-hdpi/images/loop00026.png
Binary files differ
diff --git a/res-hdpi/images/loop00027.png b/res-hdpi/images/loop00027.png
new file mode 100644
index 000000000..238dad60a
--- /dev/null
+++ b/res-hdpi/images/loop00027.png
Binary files differ
diff --git a/res-hdpi/images/loop00028.png b/res-hdpi/images/loop00028.png
new file mode 100644
index 000000000..55e058d2e
--- /dev/null
+++ b/res-hdpi/images/loop00028.png
Binary files differ
diff --git a/res-hdpi/images/loop00029.png b/res-hdpi/images/loop00029.png
new file mode 100644
index 000000000..fc761370e
--- /dev/null
+++ b/res-hdpi/images/loop00029.png
Binary files differ
diff --git a/res-hdpi/images/loop00030.png b/res-hdpi/images/loop00030.png
new file mode 100644
index 000000000..920634f89
--- /dev/null
+++ b/res-hdpi/images/loop00030.png
Binary files differ
diff --git a/res-hdpi/images/loop00031.png b/res-hdpi/images/loop00031.png
new file mode 100644
index 000000000..f54846461
--- /dev/null
+++ b/res-hdpi/images/loop00031.png
Binary files differ
diff --git a/res-hdpi/images/loop00032.png b/res-hdpi/images/loop00032.png
new file mode 100644
index 000000000..4cff5c44c
--- /dev/null
+++ b/res-hdpi/images/loop00032.png
Binary files differ
diff --git a/res-hdpi/images/loop00033.png b/res-hdpi/images/loop00033.png
new file mode 100644
index 000000000..5d2d27222
--- /dev/null
+++ b/res-hdpi/images/loop00033.png
Binary files differ
diff --git a/res-hdpi/images/loop00034.png b/res-hdpi/images/loop00034.png
new file mode 100644
index 000000000..b4d73416e
--- /dev/null
+++ b/res-hdpi/images/loop00034.png
Binary files differ
diff --git a/res-hdpi/images/loop00035.png b/res-hdpi/images/loop00035.png
new file mode 100644
index 000000000..49025b82d
--- /dev/null
+++ b/res-hdpi/images/loop00035.png
Binary files differ
diff --git a/res-hdpi/images/loop00036.png b/res-hdpi/images/loop00036.png
new file mode 100644
index 000000000..b3aa58da5
--- /dev/null
+++ b/res-hdpi/images/loop00036.png
Binary files differ
diff --git a/res-hdpi/images/loop00037.png b/res-hdpi/images/loop00037.png
new file mode 100644
index 000000000..ff47e85d6
--- /dev/null
+++ b/res-hdpi/images/loop00037.png
Binary files differ
diff --git a/res-hdpi/images/loop00038.png b/res-hdpi/images/loop00038.png
new file mode 100644
index 000000000..8039b925f
--- /dev/null
+++ b/res-hdpi/images/loop00038.png
Binary files differ
diff --git a/res-hdpi/images/loop00039.png b/res-hdpi/images/loop00039.png
new file mode 100644
index 000000000..e76d4bc96
--- /dev/null
+++ b/res-hdpi/images/loop00039.png
Binary files differ
diff --git a/res-hdpi/images/loop00040.png b/res-hdpi/images/loop00040.png
new file mode 100644
index 000000000..963cce7b6
--- /dev/null
+++ b/res-hdpi/images/loop00040.png
Binary files differ
diff --git a/res-hdpi/images/loop00041.png b/res-hdpi/images/loop00041.png
new file mode 100644
index 000000000..dcd5f1117
--- /dev/null
+++ b/res-hdpi/images/loop00041.png
Binary files differ
diff --git a/res-hdpi/images/loop00042.png b/res-hdpi/images/loop00042.png
new file mode 100644
index 000000000..72fe63ab4
--- /dev/null
+++ b/res-hdpi/images/loop00042.png
Binary files differ
diff --git a/res-hdpi/images/loop00043.png b/res-hdpi/images/loop00043.png
new file mode 100644
index 000000000..c109af88f
--- /dev/null
+++ b/res-hdpi/images/loop00043.png
Binary files differ
diff --git a/res-hdpi/images/loop00044.png b/res-hdpi/images/loop00044.png
new file mode 100644
index 000000000..6648ec226
--- /dev/null
+++ b/res-hdpi/images/loop00044.png
Binary files differ
diff --git a/res-hdpi/images/loop00045.png b/res-hdpi/images/loop00045.png
new file mode 100644
index 000000000..90bf4313d
--- /dev/null
+++ b/res-hdpi/images/loop00045.png
Binary files differ
diff --git a/res-hdpi/images/loop00046.png b/res-hdpi/images/loop00046.png
new file mode 100644
index 000000000..50473f0eb
--- /dev/null
+++ b/res-hdpi/images/loop00046.png
Binary files differ
diff --git a/res-hdpi/images/loop00047.png b/res-hdpi/images/loop00047.png
new file mode 100644
index 000000000..db4702369
--- /dev/null
+++ b/res-hdpi/images/loop00047.png
Binary files differ
diff --git a/res-hdpi/images/loop00048.png b/res-hdpi/images/loop00048.png
new file mode 100644
index 000000000..462a42131
--- /dev/null
+++ b/res-hdpi/images/loop00048.png
Binary files differ
diff --git a/res-hdpi/images/loop00049.png b/res-hdpi/images/loop00049.png
new file mode 100644
index 000000000..f86af40f2
--- /dev/null
+++ b/res-hdpi/images/loop00049.png
Binary files differ
diff --git a/res-hdpi/images/loop00050.png b/res-hdpi/images/loop00050.png
new file mode 100644
index 000000000..8c0af52ff
--- /dev/null
+++ b/res-hdpi/images/loop00050.png
Binary files differ
diff --git a/res-hdpi/images/loop00051.png b/res-hdpi/images/loop00051.png
new file mode 100644
index 000000000..2360fc0db
--- /dev/null
+++ b/res-hdpi/images/loop00051.png
Binary files differ
diff --git a/res-hdpi/images/loop00052.png b/res-hdpi/images/loop00052.png
new file mode 100644
index 000000000..dd5220018
--- /dev/null
+++ b/res-hdpi/images/loop00052.png
Binary files differ
diff --git a/res-hdpi/images/loop00053.png b/res-hdpi/images/loop00053.png
new file mode 100644
index 000000000..c7f0c1886
--- /dev/null
+++ b/res-hdpi/images/loop00053.png
Binary files differ
diff --git a/res-hdpi/images/loop00054.png b/res-hdpi/images/loop00054.png
new file mode 100644
index 000000000..7f16eff59
--- /dev/null
+++ b/res-hdpi/images/loop00054.png
Binary files differ
diff --git a/res-hdpi/images/loop00055.png b/res-hdpi/images/loop00055.png
new file mode 100644
index 000000000..b9af0ce54
--- /dev/null
+++ b/res-hdpi/images/loop00055.png
Binary files differ
diff --git a/res-hdpi/images/loop00056.png b/res-hdpi/images/loop00056.png
new file mode 100644
index 000000000..40b9e9b32
--- /dev/null
+++ b/res-hdpi/images/loop00056.png
Binary files differ
diff --git a/res-hdpi/images/loop00057.png b/res-hdpi/images/loop00057.png
new file mode 100644
index 000000000..51068cb20
--- /dev/null
+++ b/res-hdpi/images/loop00057.png
Binary files differ
diff --git a/res-hdpi/images/loop00058.png b/res-hdpi/images/loop00058.png
new file mode 100644
index 000000000..eba4486ac
--- /dev/null
+++ b/res-hdpi/images/loop00058.png
Binary files differ
diff --git a/res-hdpi/images/loop00059.png b/res-hdpi/images/loop00059.png
new file mode 100644
index 000000000..28761ac84
--- /dev/null
+++ b/res-hdpi/images/loop00059.png
Binary files differ
diff --git a/res-hdpi/images/loop00060.png b/res-hdpi/images/loop00060.png
new file mode 100644
index 000000000..6532eb93a
--- /dev/null
+++ b/res-hdpi/images/loop00060.png
Binary files differ
diff --git a/res-hdpi/images/loop00061.png b/res-hdpi/images/loop00061.png
new file mode 100644
index 000000000..fbe2e2e9d
--- /dev/null
+++ b/res-hdpi/images/loop00061.png
Binary files differ
diff --git a/res-hdpi/images/loop00062.png b/res-hdpi/images/loop00062.png
new file mode 100644
index 000000000..54341e34a
--- /dev/null
+++ b/res-hdpi/images/loop00062.png
Binary files differ
diff --git a/res-hdpi/images/loop00063.png b/res-hdpi/images/loop00063.png
new file mode 100644
index 000000000..cfe9c802c
--- /dev/null
+++ b/res-hdpi/images/loop00063.png
Binary files differ
diff --git a/res-hdpi/images/loop00064.png b/res-hdpi/images/loop00064.png
new file mode 100644
index 000000000..e1fe674ea
--- /dev/null
+++ b/res-hdpi/images/loop00064.png
Binary files differ
diff --git a/res-hdpi/images/loop00065.png b/res-hdpi/images/loop00065.png
new file mode 100644
index 000000000..efa35b64a
--- /dev/null
+++ b/res-hdpi/images/loop00065.png
Binary files differ
diff --git a/res-hdpi/images/loop00066.png b/res-hdpi/images/loop00066.png
new file mode 100644
index 000000000..d8c20fef1
--- /dev/null
+++ b/res-hdpi/images/loop00066.png
Binary files differ
diff --git a/res-hdpi/images/loop00067.png b/res-hdpi/images/loop00067.png
new file mode 100644
index 000000000..ddf1ea4cc
--- /dev/null
+++ b/res-hdpi/images/loop00067.png
Binary files differ
diff --git a/res-hdpi/images/loop00068.png b/res-hdpi/images/loop00068.png
new file mode 100644
index 000000000..827cfc6af
--- /dev/null
+++ b/res-hdpi/images/loop00068.png
Binary files differ
diff --git a/res-hdpi/images/loop00069.png b/res-hdpi/images/loop00069.png
new file mode 100644
index 000000000..6ab833f4b
--- /dev/null
+++ b/res-hdpi/images/loop00069.png
Binary files differ
diff --git a/res-hdpi/images/loop00070.png b/res-hdpi/images/loop00070.png
new file mode 100644
index 000000000..a4cc06f12
--- /dev/null
+++ b/res-hdpi/images/loop00070.png
Binary files differ
diff --git a/res-hdpi/images/loop00071.png b/res-hdpi/images/loop00071.png
new file mode 100644
index 000000000..96653c188
--- /dev/null
+++ b/res-hdpi/images/loop00071.png
Binary files differ
diff --git a/res-hdpi/images/loop00072.png b/res-hdpi/images/loop00072.png
new file mode 100644
index 000000000..44a15f874
--- /dev/null
+++ b/res-hdpi/images/loop00072.png
Binary files differ
diff --git a/res-hdpi/images/loop00073.png b/res-hdpi/images/loop00073.png
new file mode 100644
index 000000000..8352c7ce0
--- /dev/null
+++ b/res-hdpi/images/loop00073.png
Binary files differ
diff --git a/res-hdpi/images/loop00074.png b/res-hdpi/images/loop00074.png
new file mode 100644
index 000000000..914f1b7fb
--- /dev/null
+++ b/res-hdpi/images/loop00074.png
Binary files differ
diff --git a/res-hdpi/images/loop00075.png b/res-hdpi/images/loop00075.png
new file mode 100644
index 000000000..372b87139
--- /dev/null
+++ b/res-hdpi/images/loop00075.png
Binary files differ
diff --git a/res-hdpi/images/loop00076.png b/res-hdpi/images/loop00076.png
new file mode 100644
index 000000000..ffbf28570
--- /dev/null
+++ b/res-hdpi/images/loop00076.png
Binary files differ
diff --git a/res-hdpi/images/loop00077.png b/res-hdpi/images/loop00077.png
new file mode 100644
index 000000000..8dc6a4002
--- /dev/null
+++ b/res-hdpi/images/loop00077.png
Binary files differ
diff --git a/res-hdpi/images/loop00078.png b/res-hdpi/images/loop00078.png
new file mode 100644
index 000000000..cf1ea6120
--- /dev/null
+++ b/res-hdpi/images/loop00078.png
Binary files differ
diff --git a/res-hdpi/images/loop00079.png b/res-hdpi/images/loop00079.png
new file mode 100644
index 000000000..8674c822a
--- /dev/null
+++ b/res-hdpi/images/loop00079.png
Binary files differ
diff --git a/res-hdpi/images/loop00080.png b/res-hdpi/images/loop00080.png
new file mode 100644
index 000000000..3d84259bb
--- /dev/null
+++ b/res-hdpi/images/loop00080.png
Binary files differ
diff --git a/res-hdpi/images/loop00081.png b/res-hdpi/images/loop00081.png
new file mode 100644
index 000000000..aed44c53b
--- /dev/null
+++ b/res-hdpi/images/loop00081.png
Binary files differ
diff --git a/res-hdpi/images/loop00082.png b/res-hdpi/images/loop00082.png
new file mode 100644
index 000000000..a39769bdb
--- /dev/null
+++ b/res-hdpi/images/loop00082.png
Binary files differ
diff --git a/res-hdpi/images/loop00083.png b/res-hdpi/images/loop00083.png
new file mode 100644
index 000000000..905355d9e
--- /dev/null
+++ b/res-hdpi/images/loop00083.png
Binary files differ
diff --git a/res-hdpi/images/loop00084.png b/res-hdpi/images/loop00084.png
new file mode 100644
index 000000000..c86deea16
--- /dev/null
+++ b/res-hdpi/images/loop00084.png
Binary files differ
diff --git a/res-hdpi/images/loop00085.png b/res-hdpi/images/loop00085.png
new file mode 100644
index 000000000..3744ab708
--- /dev/null
+++ b/res-hdpi/images/loop00085.png
Binary files differ
diff --git a/res-hdpi/images/loop00086.png b/res-hdpi/images/loop00086.png
new file mode 100644
index 000000000..0bb9b0963
--- /dev/null
+++ b/res-hdpi/images/loop00086.png
Binary files differ
diff --git a/res-hdpi/images/loop00087.png b/res-hdpi/images/loop00087.png
new file mode 100644
index 000000000..83f97bdd0
--- /dev/null
+++ b/res-hdpi/images/loop00087.png
Binary files differ
diff --git a/res-hdpi/images/loop00088.png b/res-hdpi/images/loop00088.png
new file mode 100644
index 000000000..6fd37909a
--- /dev/null
+++ b/res-hdpi/images/loop00088.png
Binary files differ
diff --git a/res-hdpi/images/loop00089.png b/res-hdpi/images/loop00089.png
new file mode 100644
index 000000000..09500f87f
--- /dev/null
+++ b/res-hdpi/images/loop00089.png
Binary files differ
diff --git a/res-hdpi/images/loop00090.png b/res-hdpi/images/loop00090.png
new file mode 100644
index 000000000..030fa2b36
--- /dev/null
+++ b/res-hdpi/images/loop00090.png
Binary files differ
diff --git a/res-hdpi/images/no_command_text.png b/res-hdpi/images/no_command_text.png
index 9927ecb6d..a567ad141 100644
--- a/res-hdpi/images/no_command_text.png
+++ b/res-hdpi/images/no_command_text.png
Binary files differ
diff --git a/res-hdpi/images/progress_empty.png b/res-hdpi/images/progress_empty.png
index 72581832c..96c4bf6b3 100644
--- a/res-hdpi/images/progress_empty.png
+++ b/res-hdpi/images/progress_empty.png
Binary files differ
diff --git a/res-hdpi/images/progress_fill.png b/res-hdpi/images/progress_fill.png
index becf87bdf..1717be820 100644
--- a/res-hdpi/images/progress_fill.png
+++ b/res-hdpi/images/progress_fill.png
Binary files differ
diff --git a/res-mdpi/images/erasing_text.png b/res-mdpi/images/erasing_text.png
index fd86c3f6e..ad68a1941 100644
--- a/res-mdpi/images/erasing_text.png
+++ b/res-mdpi/images/erasing_text.png
Binary files differ
diff --git a/res-mdpi/images/error_text.png b/res-mdpi/images/error_text.png
index f1b44c9b3..8ea5acb20 100644
--- a/res-mdpi/images/error_text.png
+++ b/res-mdpi/images/error_text.png
Binary files differ
diff --git a/res-mdpi/images/icon_installing.png b/res-mdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc231..000000000
--- a/res-mdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-mdpi/images/installing_security_text.png b/res-mdpi/images/installing_security_text.png
new file mode 100644
index 000000000..615b9b73f
--- /dev/null
+++ b/res-mdpi/images/installing_security_text.png
Binary files differ
diff --git a/res-mdpi/images/installing_text.png b/res-mdpi/images/installing_text.png
index 064b2a317..6cf8716b5 100644
--- a/res-mdpi/images/installing_text.png
+++ b/res-mdpi/images/installing_text.png
Binary files differ
diff --git a/res-mdpi/images/loop00000.png b/res-mdpi/images/loop00000.png
new file mode 100644
index 000000000..d7092b68f
--- /dev/null
+++ b/res-mdpi/images/loop00000.png
Binary files differ
diff --git a/res-mdpi/images/loop00001.png b/res-mdpi/images/loop00001.png
new file mode 100644
index 000000000..e04a5255a
--- /dev/null
+++ b/res-mdpi/images/loop00001.png
Binary files differ
diff --git a/res-mdpi/images/loop00002.png b/res-mdpi/images/loop00002.png
new file mode 100644
index 000000000..e2a783102
--- /dev/null
+++ b/res-mdpi/images/loop00002.png
Binary files differ
diff --git a/res-mdpi/images/loop00003.png b/res-mdpi/images/loop00003.png
new file mode 100644
index 000000000..28f79bf4b
--- /dev/null
+++ b/res-mdpi/images/loop00003.png
Binary files differ
diff --git a/res-mdpi/images/loop00004.png b/res-mdpi/images/loop00004.png
new file mode 100644
index 000000000..e4bec8084
--- /dev/null
+++ b/res-mdpi/images/loop00004.png
Binary files differ
diff --git a/res-mdpi/images/loop00005.png b/res-mdpi/images/loop00005.png
new file mode 100644
index 000000000..de673e03a
--- /dev/null
+++ b/res-mdpi/images/loop00005.png
Binary files differ
diff --git a/res-mdpi/images/loop00006.png b/res-mdpi/images/loop00006.png
new file mode 100644
index 000000000..71d420311
--- /dev/null
+++ b/res-mdpi/images/loop00006.png
Binary files differ
diff --git a/res-mdpi/images/loop00007.png b/res-mdpi/images/loop00007.png
new file mode 100644
index 000000000..dee70b3b4
--- /dev/null
+++ b/res-mdpi/images/loop00007.png
Binary files differ
diff --git a/res-mdpi/images/loop00008.png b/res-mdpi/images/loop00008.png
new file mode 100644
index 000000000..9eccc7fe4
--- /dev/null
+++ b/res-mdpi/images/loop00008.png
Binary files differ
diff --git a/res-mdpi/images/loop00009.png b/res-mdpi/images/loop00009.png
new file mode 100644
index 000000000..d6672ac0f
--- /dev/null
+++ b/res-mdpi/images/loop00009.png
Binary files differ
diff --git a/res-mdpi/images/loop00010.png b/res-mdpi/images/loop00010.png
new file mode 100644
index 000000000..1bb8f5c38
--- /dev/null
+++ b/res-mdpi/images/loop00010.png
Binary files differ
diff --git a/res-mdpi/images/loop00011.png b/res-mdpi/images/loop00011.png
new file mode 100644
index 000000000..849ce3dd0
--- /dev/null
+++ b/res-mdpi/images/loop00011.png
Binary files differ
diff --git a/res-mdpi/images/loop00012.png b/res-mdpi/images/loop00012.png
new file mode 100644
index 000000000..cee9dcf04
--- /dev/null
+++ b/res-mdpi/images/loop00012.png
Binary files differ
diff --git a/res-mdpi/images/loop00013.png b/res-mdpi/images/loop00013.png
new file mode 100644
index 000000000..1ef61d734
--- /dev/null
+++ b/res-mdpi/images/loop00013.png
Binary files differ
diff --git a/res-mdpi/images/loop00014.png b/res-mdpi/images/loop00014.png
new file mode 100644
index 000000000..bc84637bd
--- /dev/null
+++ b/res-mdpi/images/loop00014.png
Binary files differ
diff --git a/res-mdpi/images/loop00015.png b/res-mdpi/images/loop00015.png
new file mode 100644
index 000000000..f5607f237
--- /dev/null
+++ b/res-mdpi/images/loop00015.png
Binary files differ
diff --git a/res-mdpi/images/loop00016.png b/res-mdpi/images/loop00016.png
new file mode 100644
index 000000000..235527c33
--- /dev/null
+++ b/res-mdpi/images/loop00016.png
Binary files differ
diff --git a/res-mdpi/images/loop00017.png b/res-mdpi/images/loop00017.png
new file mode 100644
index 000000000..88307a6b6
--- /dev/null
+++ b/res-mdpi/images/loop00017.png
Binary files differ
diff --git a/res-mdpi/images/loop00018.png b/res-mdpi/images/loop00018.png
new file mode 100644
index 000000000..02472d753
--- /dev/null
+++ b/res-mdpi/images/loop00018.png
Binary files differ
diff --git a/res-mdpi/images/loop00019.png b/res-mdpi/images/loop00019.png
new file mode 100644
index 000000000..f06bdaae5
--- /dev/null
+++ b/res-mdpi/images/loop00019.png
Binary files differ
diff --git a/res-mdpi/images/loop00020.png b/res-mdpi/images/loop00020.png
new file mode 100644
index 000000000..dc522c071
--- /dev/null
+++ b/res-mdpi/images/loop00020.png
Binary files differ
diff --git a/res-mdpi/images/loop00021.png b/res-mdpi/images/loop00021.png
new file mode 100644
index 000000000..3a53ee53d
--- /dev/null
+++ b/res-mdpi/images/loop00021.png
Binary files differ
diff --git a/res-mdpi/images/loop00022.png b/res-mdpi/images/loop00022.png
new file mode 100644
index 000000000..09b8eea14
--- /dev/null
+++ b/res-mdpi/images/loop00022.png
Binary files differ
diff --git a/res-mdpi/images/loop00023.png b/res-mdpi/images/loop00023.png
new file mode 100644
index 000000000..ebc677d41
--- /dev/null
+++ b/res-mdpi/images/loop00023.png
Binary files differ
diff --git a/res-mdpi/images/loop00024.png b/res-mdpi/images/loop00024.png
new file mode 100644
index 000000000..a4fd8e508
--- /dev/null
+++ b/res-mdpi/images/loop00024.png
Binary files differ
diff --git a/res-mdpi/images/loop00025.png b/res-mdpi/images/loop00025.png
new file mode 100644
index 000000000..9435624ee
--- /dev/null
+++ b/res-mdpi/images/loop00025.png
Binary files differ
diff --git a/res-mdpi/images/loop00026.png b/res-mdpi/images/loop00026.png
new file mode 100644
index 000000000..b7e808154
--- /dev/null
+++ b/res-mdpi/images/loop00026.png
Binary files differ
diff --git a/res-mdpi/images/loop00027.png b/res-mdpi/images/loop00027.png
new file mode 100644
index 000000000..757d8ed90
--- /dev/null
+++ b/res-mdpi/images/loop00027.png
Binary files differ
diff --git a/res-mdpi/images/loop00028.png b/res-mdpi/images/loop00028.png
new file mode 100644
index 000000000..8eefa3a57
--- /dev/null
+++ b/res-mdpi/images/loop00028.png
Binary files differ
diff --git a/res-mdpi/images/loop00029.png b/res-mdpi/images/loop00029.png
new file mode 100644
index 000000000..8d890dee6
--- /dev/null
+++ b/res-mdpi/images/loop00029.png
Binary files differ
diff --git a/res-mdpi/images/loop00030.png b/res-mdpi/images/loop00030.png
new file mode 100644
index 000000000..8e0eeb6f8
--- /dev/null
+++ b/res-mdpi/images/loop00030.png
Binary files differ
diff --git a/res-mdpi/images/loop00031.png b/res-mdpi/images/loop00031.png
new file mode 100644
index 000000000..178b29d6e
--- /dev/null
+++ b/res-mdpi/images/loop00031.png
Binary files differ
diff --git a/res-mdpi/images/loop00032.png b/res-mdpi/images/loop00032.png
new file mode 100644
index 000000000..39192c75a
--- /dev/null
+++ b/res-mdpi/images/loop00032.png
Binary files differ
diff --git a/res-mdpi/images/loop00033.png b/res-mdpi/images/loop00033.png
new file mode 100644
index 000000000..0647e5001
--- /dev/null
+++ b/res-mdpi/images/loop00033.png
Binary files differ
diff --git a/res-mdpi/images/loop00034.png b/res-mdpi/images/loop00034.png
new file mode 100644
index 000000000..d6bc079a6
--- /dev/null
+++ b/res-mdpi/images/loop00034.png
Binary files differ
diff --git a/res-mdpi/images/loop00035.png b/res-mdpi/images/loop00035.png
new file mode 100644
index 000000000..68352e85c
--- /dev/null
+++ b/res-mdpi/images/loop00035.png
Binary files differ
diff --git a/res-mdpi/images/loop00036.png b/res-mdpi/images/loop00036.png
new file mode 100644
index 000000000..92d9da27b
--- /dev/null
+++ b/res-mdpi/images/loop00036.png
Binary files differ
diff --git a/res-mdpi/images/loop00037.png b/res-mdpi/images/loop00037.png
new file mode 100644
index 000000000..a0e4d337f
--- /dev/null
+++ b/res-mdpi/images/loop00037.png
Binary files differ
diff --git a/res-mdpi/images/loop00038.png b/res-mdpi/images/loop00038.png
new file mode 100644
index 000000000..c52317363
--- /dev/null
+++ b/res-mdpi/images/loop00038.png
Binary files differ
diff --git a/res-mdpi/images/loop00039.png b/res-mdpi/images/loop00039.png
new file mode 100644
index 000000000..aae776583
--- /dev/null
+++ b/res-mdpi/images/loop00039.png
Binary files differ
diff --git a/res-mdpi/images/loop00040.png b/res-mdpi/images/loop00040.png
new file mode 100644
index 000000000..af9e0188b
--- /dev/null
+++ b/res-mdpi/images/loop00040.png
Binary files differ
diff --git a/res-mdpi/images/loop00041.png b/res-mdpi/images/loop00041.png
new file mode 100644
index 000000000..8e089c200
--- /dev/null
+++ b/res-mdpi/images/loop00041.png
Binary files differ
diff --git a/res-mdpi/images/loop00042.png b/res-mdpi/images/loop00042.png
new file mode 100644
index 000000000..e3e3b8a49
--- /dev/null
+++ b/res-mdpi/images/loop00042.png
Binary files differ
diff --git a/res-mdpi/images/loop00043.png b/res-mdpi/images/loop00043.png
new file mode 100644
index 000000000..cc8acbaeb
--- /dev/null
+++ b/res-mdpi/images/loop00043.png
Binary files differ
diff --git a/res-mdpi/images/loop00044.png b/res-mdpi/images/loop00044.png
new file mode 100644
index 000000000..9a3a9b998
--- /dev/null
+++ b/res-mdpi/images/loop00044.png
Binary files differ
diff --git a/res-mdpi/images/loop00045.png b/res-mdpi/images/loop00045.png
new file mode 100644
index 000000000..ec5e3c4d1
--- /dev/null
+++ b/res-mdpi/images/loop00045.png
Binary files differ
diff --git a/res-mdpi/images/loop00046.png b/res-mdpi/images/loop00046.png
new file mode 100644
index 000000000..925e2b788
--- /dev/null
+++ b/res-mdpi/images/loop00046.png
Binary files differ
diff --git a/res-mdpi/images/loop00047.png b/res-mdpi/images/loop00047.png
new file mode 100644
index 000000000..62fff8864
--- /dev/null
+++ b/res-mdpi/images/loop00047.png
Binary files differ
diff --git a/res-mdpi/images/loop00048.png b/res-mdpi/images/loop00048.png
new file mode 100644
index 000000000..46efe7032
--- /dev/null
+++ b/res-mdpi/images/loop00048.png
Binary files differ
diff --git a/res-mdpi/images/loop00049.png b/res-mdpi/images/loop00049.png
new file mode 100644
index 000000000..678dce473
--- /dev/null
+++ b/res-mdpi/images/loop00049.png
Binary files differ
diff --git a/res-mdpi/images/loop00050.png b/res-mdpi/images/loop00050.png
new file mode 100644
index 000000000..cbc6fdbf0
--- /dev/null
+++ b/res-mdpi/images/loop00050.png
Binary files differ
diff --git a/res-mdpi/images/loop00051.png b/res-mdpi/images/loop00051.png
new file mode 100644
index 000000000..afa906677
--- /dev/null
+++ b/res-mdpi/images/loop00051.png
Binary files differ
diff --git a/res-mdpi/images/loop00052.png b/res-mdpi/images/loop00052.png
new file mode 100644
index 000000000..4d2d98c53
--- /dev/null
+++ b/res-mdpi/images/loop00052.png
Binary files differ
diff --git a/res-mdpi/images/loop00053.png b/res-mdpi/images/loop00053.png
new file mode 100644
index 000000000..48136a5da
--- /dev/null
+++ b/res-mdpi/images/loop00053.png
Binary files differ
diff --git a/res-mdpi/images/loop00054.png b/res-mdpi/images/loop00054.png
new file mode 100644
index 000000000..09f706af6
--- /dev/null
+++ b/res-mdpi/images/loop00054.png
Binary files differ
diff --git a/res-mdpi/images/loop00055.png b/res-mdpi/images/loop00055.png
new file mode 100644
index 000000000..7565a1c21
--- /dev/null
+++ b/res-mdpi/images/loop00055.png
Binary files differ
diff --git a/res-mdpi/images/loop00056.png b/res-mdpi/images/loop00056.png
new file mode 100644
index 000000000..2765831a9
--- /dev/null
+++ b/res-mdpi/images/loop00056.png
Binary files differ
diff --git a/res-mdpi/images/loop00057.png b/res-mdpi/images/loop00057.png
new file mode 100644
index 000000000..de440e0dd
--- /dev/null
+++ b/res-mdpi/images/loop00057.png
Binary files differ
diff --git a/res-mdpi/images/loop00058.png b/res-mdpi/images/loop00058.png
new file mode 100644
index 000000000..67d49c78f
--- /dev/null
+++ b/res-mdpi/images/loop00058.png
Binary files differ
diff --git a/res-mdpi/images/loop00059.png b/res-mdpi/images/loop00059.png
new file mode 100644
index 000000000..a622f4587
--- /dev/null
+++ b/res-mdpi/images/loop00059.png
Binary files differ
diff --git a/res-mdpi/images/loop00060.png b/res-mdpi/images/loop00060.png
new file mode 100644
index 000000000..06d6eec8b
--- /dev/null
+++ b/res-mdpi/images/loop00060.png
Binary files differ
diff --git a/res-mdpi/images/loop00061.png b/res-mdpi/images/loop00061.png
new file mode 100644
index 000000000..7f11945a0
--- /dev/null
+++ b/res-mdpi/images/loop00061.png
Binary files differ
diff --git a/res-mdpi/images/loop00062.png b/res-mdpi/images/loop00062.png
new file mode 100644
index 000000000..8197c94cf
--- /dev/null
+++ b/res-mdpi/images/loop00062.png
Binary files differ
diff --git a/res-mdpi/images/loop00063.png b/res-mdpi/images/loop00063.png
new file mode 100644
index 000000000..4093c9b06
--- /dev/null
+++ b/res-mdpi/images/loop00063.png
Binary files differ
diff --git a/res-mdpi/images/loop00064.png b/res-mdpi/images/loop00064.png
new file mode 100644
index 000000000..d09bd1ebd
--- /dev/null
+++ b/res-mdpi/images/loop00064.png
Binary files differ
diff --git a/res-mdpi/images/loop00065.png b/res-mdpi/images/loop00065.png
new file mode 100644
index 000000000..cbb6c1b80
--- /dev/null
+++ b/res-mdpi/images/loop00065.png
Binary files differ
diff --git a/res-mdpi/images/loop00066.png b/res-mdpi/images/loop00066.png
new file mode 100644
index 000000000..aed0a700a
--- /dev/null
+++ b/res-mdpi/images/loop00066.png
Binary files differ
diff --git a/res-mdpi/images/loop00067.png b/res-mdpi/images/loop00067.png
new file mode 100644
index 000000000..dd0da799f
--- /dev/null
+++ b/res-mdpi/images/loop00067.png
Binary files differ
diff --git a/res-mdpi/images/loop00068.png b/res-mdpi/images/loop00068.png
new file mode 100644
index 000000000..161802c8e
--- /dev/null
+++ b/res-mdpi/images/loop00068.png
Binary files differ
diff --git a/res-mdpi/images/loop00069.png b/res-mdpi/images/loop00069.png
new file mode 100644
index 000000000..4ee0372a5
--- /dev/null
+++ b/res-mdpi/images/loop00069.png
Binary files differ
diff --git a/res-mdpi/images/loop00070.png b/res-mdpi/images/loop00070.png
new file mode 100644
index 000000000..41a64fff6
--- /dev/null
+++ b/res-mdpi/images/loop00070.png
Binary files differ
diff --git a/res-mdpi/images/loop00071.png b/res-mdpi/images/loop00071.png
new file mode 100644
index 000000000..c4793d79c
--- /dev/null
+++ b/res-mdpi/images/loop00071.png
Binary files differ
diff --git a/res-mdpi/images/loop00072.png b/res-mdpi/images/loop00072.png
new file mode 100644
index 000000000..9399d193c
--- /dev/null
+++ b/res-mdpi/images/loop00072.png
Binary files differ
diff --git a/res-mdpi/images/loop00073.png b/res-mdpi/images/loop00073.png
new file mode 100644
index 000000000..d4e55adc9
--- /dev/null
+++ b/res-mdpi/images/loop00073.png
Binary files differ
diff --git a/res-mdpi/images/loop00074.png b/res-mdpi/images/loop00074.png
new file mode 100644
index 000000000..f29a0af5f
--- /dev/null
+++ b/res-mdpi/images/loop00074.png
Binary files differ
diff --git a/res-mdpi/images/loop00075.png b/res-mdpi/images/loop00075.png
new file mode 100644
index 000000000..020568e4a
--- /dev/null
+++ b/res-mdpi/images/loop00075.png
Binary files differ
diff --git a/res-mdpi/images/loop00076.png b/res-mdpi/images/loop00076.png
new file mode 100644
index 000000000..51a54cc98
--- /dev/null
+++ b/res-mdpi/images/loop00076.png
Binary files differ
diff --git a/res-mdpi/images/loop00077.png b/res-mdpi/images/loop00077.png
new file mode 100644
index 000000000..f6e80a918
--- /dev/null
+++ b/res-mdpi/images/loop00077.png
Binary files differ
diff --git a/res-mdpi/images/loop00078.png b/res-mdpi/images/loop00078.png
new file mode 100644
index 000000000..944452120
--- /dev/null
+++ b/res-mdpi/images/loop00078.png
Binary files differ
diff --git a/res-mdpi/images/loop00079.png b/res-mdpi/images/loop00079.png
new file mode 100644
index 000000000..b1ef2c308
--- /dev/null
+++ b/res-mdpi/images/loop00079.png
Binary files differ
diff --git a/res-mdpi/images/loop00080.png b/res-mdpi/images/loop00080.png
new file mode 100644
index 000000000..8a911fba8
--- /dev/null
+++ b/res-mdpi/images/loop00080.png
Binary files differ
diff --git a/res-mdpi/images/loop00081.png b/res-mdpi/images/loop00081.png
new file mode 100644
index 000000000..f848df4c8
--- /dev/null
+++ b/res-mdpi/images/loop00081.png
Binary files differ
diff --git a/res-mdpi/images/loop00082.png b/res-mdpi/images/loop00082.png
new file mode 100644
index 000000000..35b1325aa
--- /dev/null
+++ b/res-mdpi/images/loop00082.png
Binary files differ
diff --git a/res-mdpi/images/loop00083.png b/res-mdpi/images/loop00083.png
new file mode 100644
index 000000000..1571fb5a4
--- /dev/null
+++ b/res-mdpi/images/loop00083.png
Binary files differ
diff --git a/res-mdpi/images/loop00084.png b/res-mdpi/images/loop00084.png
new file mode 100644
index 000000000..92b529509
--- /dev/null
+++ b/res-mdpi/images/loop00084.png
Binary files differ
diff --git a/res-mdpi/images/loop00085.png b/res-mdpi/images/loop00085.png
new file mode 100644
index 000000000..cde8880c7
--- /dev/null
+++ b/res-mdpi/images/loop00085.png
Binary files differ
diff --git a/res-mdpi/images/loop00086.png b/res-mdpi/images/loop00086.png
new file mode 100644
index 000000000..45889e551
--- /dev/null
+++ b/res-mdpi/images/loop00086.png
Binary files differ
diff --git a/res-mdpi/images/loop00087.png b/res-mdpi/images/loop00087.png
new file mode 100644
index 000000000..9cad9aa39
--- /dev/null
+++ b/res-mdpi/images/loop00087.png
Binary files differ
diff --git a/res-mdpi/images/loop00088.png b/res-mdpi/images/loop00088.png
new file mode 100644
index 000000000..dcf98c8b6
--- /dev/null
+++ b/res-mdpi/images/loop00088.png
Binary files differ
diff --git a/res-mdpi/images/loop00089.png b/res-mdpi/images/loop00089.png
new file mode 100644
index 000000000..584cb8994
--- /dev/null
+++ b/res-mdpi/images/loop00089.png
Binary files differ
diff --git a/res-mdpi/images/loop00090.png b/res-mdpi/images/loop00090.png
new file mode 100644
index 000000000..d7092b68f
--- /dev/null
+++ b/res-mdpi/images/loop00090.png
Binary files differ
diff --git a/res-mdpi/images/no_command_text.png b/res-mdpi/images/no_command_text.png
index 1f29b8951..5cc6b3715 100644
--- a/res-mdpi/images/no_command_text.png
+++ b/res-mdpi/images/no_command_text.png
Binary files differ
diff --git a/res-mdpi/images/progress_empty.png b/res-mdpi/images/progress_empty.png
index 72581832c..96c4bf6b3 100644
--- a/res-mdpi/images/progress_empty.png
+++ b/res-mdpi/images/progress_empty.png
Binary files differ
diff --git a/res-mdpi/images/progress_fill.png b/res-mdpi/images/progress_fill.png
index becf87bdf..1717be820 100644
--- a/res-mdpi/images/progress_fill.png
+++ b/res-mdpi/images/progress_fill.png
Binary files differ
diff --git a/res-xhdpi/images/erasing_text.png b/res-xhdpi/images/erasing_text.png
index f88e0e6a8..01176e8cc 100644
--- a/res-xhdpi/images/erasing_text.png
+++ b/res-xhdpi/images/erasing_text.png
Binary files differ
diff --git a/res-xhdpi/images/error_text.png b/res-xhdpi/images/error_text.png
index c3a4cc6f8..4f890fa59 100644
--- a/res-xhdpi/images/error_text.png
+++ b/res-xhdpi/images/error_text.png
Binary files differ
diff --git a/res-xhdpi/images/icon_installing.png b/res-xhdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc231..000000000
--- a/res-xhdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-xhdpi/images/installing_security_text.png b/res-xhdpi/images/installing_security_text.png
new file mode 100644
index 000000000..6192832e8
--- /dev/null
+++ b/res-xhdpi/images/installing_security_text.png
Binary files differ
diff --git a/res-xhdpi/images/installing_text.png b/res-xhdpi/images/installing_text.png
index a4dacd0f6..441352949 100644
--- a/res-xhdpi/images/installing_text.png
+++ b/res-xhdpi/images/installing_text.png
Binary files differ
diff --git a/res-xhdpi/images/loop00000.png b/res-xhdpi/images/loop00000.png
new file mode 100644
index 000000000..f5bf7a73b
--- /dev/null
+++ b/res-xhdpi/images/loop00000.png
Binary files differ
diff --git a/res-xhdpi/images/loop00001.png b/res-xhdpi/images/loop00001.png
new file mode 100644
index 000000000..95c14ebf3
--- /dev/null
+++ b/res-xhdpi/images/loop00001.png
Binary files differ
diff --git a/res-xhdpi/images/loop00002.png b/res-xhdpi/images/loop00002.png
new file mode 100644
index 000000000..5910fd106
--- /dev/null
+++ b/res-xhdpi/images/loop00002.png
Binary files differ
diff --git a/res-xhdpi/images/loop00003.png b/res-xhdpi/images/loop00003.png
new file mode 100644
index 000000000..e6861d2a2
--- /dev/null
+++ b/res-xhdpi/images/loop00003.png
Binary files differ
diff --git a/res-xhdpi/images/loop00004.png b/res-xhdpi/images/loop00004.png
new file mode 100644
index 000000000..453cdc615
--- /dev/null
+++ b/res-xhdpi/images/loop00004.png
Binary files differ
diff --git a/res-xhdpi/images/loop00005.png b/res-xhdpi/images/loop00005.png
new file mode 100644
index 000000000..12157c961
--- /dev/null
+++ b/res-xhdpi/images/loop00005.png
Binary files differ
diff --git a/res-xhdpi/images/loop00006.png b/res-xhdpi/images/loop00006.png
new file mode 100644
index 000000000..5e7838535
--- /dev/null
+++ b/res-xhdpi/images/loop00006.png
Binary files differ
diff --git a/res-xhdpi/images/loop00007.png b/res-xhdpi/images/loop00007.png
new file mode 100644
index 000000000..c69abf4f2
--- /dev/null
+++ b/res-xhdpi/images/loop00007.png
Binary files differ
diff --git a/res-xhdpi/images/loop00008.png b/res-xhdpi/images/loop00008.png
new file mode 100644
index 000000000..78c3b993c
--- /dev/null
+++ b/res-xhdpi/images/loop00008.png
Binary files differ
diff --git a/res-xhdpi/images/loop00009.png b/res-xhdpi/images/loop00009.png
new file mode 100644
index 000000000..e510b6b80
--- /dev/null
+++ b/res-xhdpi/images/loop00009.png
Binary files differ
diff --git a/res-xhdpi/images/loop00010.png b/res-xhdpi/images/loop00010.png
new file mode 100644
index 000000000..9d775faa4
--- /dev/null
+++ b/res-xhdpi/images/loop00010.png
Binary files differ
diff --git a/res-xhdpi/images/loop00011.png b/res-xhdpi/images/loop00011.png
new file mode 100644
index 000000000..36c01957e
--- /dev/null
+++ b/res-xhdpi/images/loop00011.png
Binary files differ
diff --git a/res-xhdpi/images/loop00012.png b/res-xhdpi/images/loop00012.png
new file mode 100644
index 000000000..ac65096d9
--- /dev/null
+++ b/res-xhdpi/images/loop00012.png
Binary files differ
diff --git a/res-xhdpi/images/loop00013.png b/res-xhdpi/images/loop00013.png
new file mode 100644
index 000000000..e3fdaafa7
--- /dev/null
+++ b/res-xhdpi/images/loop00013.png
Binary files differ
diff --git a/res-xhdpi/images/loop00014.png b/res-xhdpi/images/loop00014.png
new file mode 100644
index 000000000..6e85108df
--- /dev/null
+++ b/res-xhdpi/images/loop00014.png
Binary files differ
diff --git a/res-xhdpi/images/loop00015.png b/res-xhdpi/images/loop00015.png
new file mode 100644
index 000000000..9e6032951
--- /dev/null
+++ b/res-xhdpi/images/loop00015.png
Binary files differ
diff --git a/res-xhdpi/images/loop00016.png b/res-xhdpi/images/loop00016.png
new file mode 100644
index 000000000..68417aa54
--- /dev/null
+++ b/res-xhdpi/images/loop00016.png
Binary files differ
diff --git a/res-xhdpi/images/loop00017.png b/res-xhdpi/images/loop00017.png
new file mode 100644
index 000000000..4ac5dded3
--- /dev/null
+++ b/res-xhdpi/images/loop00017.png
Binary files differ
diff --git a/res-xhdpi/images/loop00018.png b/res-xhdpi/images/loop00018.png
new file mode 100644
index 000000000..d6511287e
--- /dev/null
+++ b/res-xhdpi/images/loop00018.png
Binary files differ
diff --git a/res-xhdpi/images/loop00019.png b/res-xhdpi/images/loop00019.png
new file mode 100644
index 000000000..374273574
--- /dev/null
+++ b/res-xhdpi/images/loop00019.png
Binary files differ
diff --git a/res-xhdpi/images/loop00020.png b/res-xhdpi/images/loop00020.png
new file mode 100644
index 000000000..04489a10f
--- /dev/null
+++ b/res-xhdpi/images/loop00020.png
Binary files differ
diff --git a/res-xhdpi/images/loop00021.png b/res-xhdpi/images/loop00021.png
new file mode 100644
index 000000000..59c70166c
--- /dev/null
+++ b/res-xhdpi/images/loop00021.png
Binary files differ
diff --git a/res-xhdpi/images/loop00022.png b/res-xhdpi/images/loop00022.png
new file mode 100644
index 000000000..0b9a59f38
--- /dev/null
+++ b/res-xhdpi/images/loop00022.png
Binary files differ
diff --git a/res-xhdpi/images/loop00023.png b/res-xhdpi/images/loop00023.png
new file mode 100644
index 000000000..31abae79f
--- /dev/null
+++ b/res-xhdpi/images/loop00023.png
Binary files differ
diff --git a/res-xhdpi/images/loop00024.png b/res-xhdpi/images/loop00024.png
new file mode 100644
index 000000000..98d8ee39c
--- /dev/null
+++ b/res-xhdpi/images/loop00024.png
Binary files differ
diff --git a/res-xhdpi/images/loop00025.png b/res-xhdpi/images/loop00025.png
new file mode 100644
index 000000000..9f074d266
--- /dev/null
+++ b/res-xhdpi/images/loop00025.png
Binary files differ
diff --git a/res-xhdpi/images/loop00026.png b/res-xhdpi/images/loop00026.png
new file mode 100644
index 000000000..063fca2de
--- /dev/null
+++ b/res-xhdpi/images/loop00026.png
Binary files differ
diff --git a/res-xhdpi/images/loop00027.png b/res-xhdpi/images/loop00027.png
new file mode 100644
index 000000000..67e503a70
--- /dev/null
+++ b/res-xhdpi/images/loop00027.png
Binary files differ
diff --git a/res-xhdpi/images/loop00028.png b/res-xhdpi/images/loop00028.png
new file mode 100644
index 000000000..7e76be845
--- /dev/null
+++ b/res-xhdpi/images/loop00028.png
Binary files differ
diff --git a/res-xhdpi/images/loop00029.png b/res-xhdpi/images/loop00029.png
new file mode 100644
index 000000000..4902f6b5e
--- /dev/null
+++ b/res-xhdpi/images/loop00029.png
Binary files differ
diff --git a/res-xhdpi/images/loop00030.png b/res-xhdpi/images/loop00030.png
new file mode 100644
index 000000000..387b893b0
--- /dev/null
+++ b/res-xhdpi/images/loop00030.png
Binary files differ
diff --git a/res-xhdpi/images/loop00031.png b/res-xhdpi/images/loop00031.png
new file mode 100644
index 000000000..ad116280f
--- /dev/null
+++ b/res-xhdpi/images/loop00031.png
Binary files differ
diff --git a/res-xhdpi/images/loop00032.png b/res-xhdpi/images/loop00032.png
new file mode 100644
index 000000000..7d809e6b2
--- /dev/null
+++ b/res-xhdpi/images/loop00032.png
Binary files differ
diff --git a/res-xhdpi/images/loop00033.png b/res-xhdpi/images/loop00033.png
new file mode 100644
index 000000000..59fcdc108
--- /dev/null
+++ b/res-xhdpi/images/loop00033.png
Binary files differ
diff --git a/res-xhdpi/images/loop00034.png b/res-xhdpi/images/loop00034.png
new file mode 100644
index 000000000..cb4301c31
--- /dev/null
+++ b/res-xhdpi/images/loop00034.png
Binary files differ
diff --git a/res-xhdpi/images/loop00035.png b/res-xhdpi/images/loop00035.png
new file mode 100644
index 000000000..6b1687807
--- /dev/null
+++ b/res-xhdpi/images/loop00035.png
Binary files differ
diff --git a/res-xhdpi/images/loop00036.png b/res-xhdpi/images/loop00036.png
new file mode 100644
index 000000000..3aa78502f
--- /dev/null
+++ b/res-xhdpi/images/loop00036.png
Binary files differ
diff --git a/res-xhdpi/images/loop00037.png b/res-xhdpi/images/loop00037.png
new file mode 100644
index 000000000..a60e8512c
--- /dev/null
+++ b/res-xhdpi/images/loop00037.png
Binary files differ
diff --git a/res-xhdpi/images/loop00038.png b/res-xhdpi/images/loop00038.png
new file mode 100644
index 000000000..50107f3aa
--- /dev/null
+++ b/res-xhdpi/images/loop00038.png
Binary files differ
diff --git a/res-xhdpi/images/loop00039.png b/res-xhdpi/images/loop00039.png
new file mode 100644
index 000000000..c85201e25
--- /dev/null
+++ b/res-xhdpi/images/loop00039.png
Binary files differ
diff --git a/res-xhdpi/images/loop00040.png b/res-xhdpi/images/loop00040.png
new file mode 100644
index 000000000..6ae161218
--- /dev/null
+++ b/res-xhdpi/images/loop00040.png
Binary files differ
diff --git a/res-xhdpi/images/loop00041.png b/res-xhdpi/images/loop00041.png
new file mode 100644
index 000000000..7602b04a7
--- /dev/null
+++ b/res-xhdpi/images/loop00041.png
Binary files differ
diff --git a/res-xhdpi/images/loop00042.png b/res-xhdpi/images/loop00042.png
new file mode 100644
index 000000000..054da6d75
--- /dev/null
+++ b/res-xhdpi/images/loop00042.png
Binary files differ
diff --git a/res-xhdpi/images/loop00043.png b/res-xhdpi/images/loop00043.png
new file mode 100644
index 000000000..d28be8b8e
--- /dev/null
+++ b/res-xhdpi/images/loop00043.png
Binary files differ
diff --git a/res-xhdpi/images/loop00044.png b/res-xhdpi/images/loop00044.png
new file mode 100644
index 000000000..83271268f
--- /dev/null
+++ b/res-xhdpi/images/loop00044.png
Binary files differ
diff --git a/res-xhdpi/images/loop00045.png b/res-xhdpi/images/loop00045.png
new file mode 100644
index 000000000..d749e22d7
--- /dev/null
+++ b/res-xhdpi/images/loop00045.png
Binary files differ
diff --git a/res-xhdpi/images/loop00046.png b/res-xhdpi/images/loop00046.png
new file mode 100644
index 000000000..60025d1be
--- /dev/null
+++ b/res-xhdpi/images/loop00046.png
Binary files differ
diff --git a/res-xhdpi/images/loop00047.png b/res-xhdpi/images/loop00047.png
new file mode 100644
index 000000000..b0be5c69c
--- /dev/null
+++ b/res-xhdpi/images/loop00047.png
Binary files differ
diff --git a/res-xhdpi/images/loop00048.png b/res-xhdpi/images/loop00048.png
new file mode 100644
index 000000000..be926d9f2
--- /dev/null
+++ b/res-xhdpi/images/loop00048.png
Binary files differ
diff --git a/res-xhdpi/images/loop00049.png b/res-xhdpi/images/loop00049.png
new file mode 100644
index 000000000..456085442
--- /dev/null
+++ b/res-xhdpi/images/loop00049.png
Binary files differ
diff --git a/res-xhdpi/images/loop00050.png b/res-xhdpi/images/loop00050.png
new file mode 100644
index 000000000..967dd87ff
--- /dev/null
+++ b/res-xhdpi/images/loop00050.png
Binary files differ
diff --git a/res-xhdpi/images/loop00051.png b/res-xhdpi/images/loop00051.png
new file mode 100644
index 000000000..c1698597a
--- /dev/null
+++ b/res-xhdpi/images/loop00051.png
Binary files differ
diff --git a/res-xhdpi/images/loop00052.png b/res-xhdpi/images/loop00052.png
new file mode 100644
index 000000000..27c23830a
--- /dev/null
+++ b/res-xhdpi/images/loop00052.png
Binary files differ
diff --git a/res-xhdpi/images/loop00053.png b/res-xhdpi/images/loop00053.png
new file mode 100644
index 000000000..cd2ca21c8
--- /dev/null
+++ b/res-xhdpi/images/loop00053.png
Binary files differ
diff --git a/res-xhdpi/images/loop00054.png b/res-xhdpi/images/loop00054.png
new file mode 100644
index 000000000..588586b3a
--- /dev/null
+++ b/res-xhdpi/images/loop00054.png
Binary files differ
diff --git a/res-xhdpi/images/loop00055.png b/res-xhdpi/images/loop00055.png
new file mode 100644
index 000000000..0984d01fe
--- /dev/null
+++ b/res-xhdpi/images/loop00055.png
Binary files differ
diff --git a/res-xhdpi/images/loop00056.png b/res-xhdpi/images/loop00056.png
new file mode 100644
index 000000000..bab299846
--- /dev/null
+++ b/res-xhdpi/images/loop00056.png
Binary files differ
diff --git a/res-xhdpi/images/loop00057.png b/res-xhdpi/images/loop00057.png
new file mode 100644
index 000000000..4acfce540
--- /dev/null
+++ b/res-xhdpi/images/loop00057.png
Binary files differ
diff --git a/res-xhdpi/images/loop00058.png b/res-xhdpi/images/loop00058.png
new file mode 100644
index 000000000..d49fea46f
--- /dev/null
+++ b/res-xhdpi/images/loop00058.png
Binary files differ
diff --git a/res-xhdpi/images/loop00059.png b/res-xhdpi/images/loop00059.png
new file mode 100644
index 000000000..fdd75c6b9
--- /dev/null
+++ b/res-xhdpi/images/loop00059.png
Binary files differ
diff --git a/res-xhdpi/images/loop00060.png b/res-xhdpi/images/loop00060.png
new file mode 100644
index 000000000..06ac591ef
--- /dev/null
+++ b/res-xhdpi/images/loop00060.png
Binary files differ
diff --git a/res-xhdpi/images/loop00061.png b/res-xhdpi/images/loop00061.png
new file mode 100644
index 000000000..63be53676
--- /dev/null
+++ b/res-xhdpi/images/loop00061.png
Binary files differ
diff --git a/res-xhdpi/images/loop00062.png b/res-xhdpi/images/loop00062.png
new file mode 100644
index 000000000..e25c906cb
--- /dev/null
+++ b/res-xhdpi/images/loop00062.png
Binary files differ
diff --git a/res-xhdpi/images/loop00063.png b/res-xhdpi/images/loop00063.png
new file mode 100644
index 000000000..1fcaefe25
--- /dev/null
+++ b/res-xhdpi/images/loop00063.png
Binary files differ
diff --git a/res-xhdpi/images/loop00064.png b/res-xhdpi/images/loop00064.png
new file mode 100644
index 000000000..fe373d042
--- /dev/null
+++ b/res-xhdpi/images/loop00064.png
Binary files differ
diff --git a/res-xhdpi/images/loop00065.png b/res-xhdpi/images/loop00065.png
new file mode 100644
index 000000000..c5feed6ed
--- /dev/null
+++ b/res-xhdpi/images/loop00065.png
Binary files differ
diff --git a/res-xhdpi/images/loop00066.png b/res-xhdpi/images/loop00066.png
new file mode 100644
index 000000000..bc336e755
--- /dev/null
+++ b/res-xhdpi/images/loop00066.png
Binary files differ
diff --git a/res-xhdpi/images/loop00067.png b/res-xhdpi/images/loop00067.png
new file mode 100644
index 000000000..a4cdcaea4
--- /dev/null
+++ b/res-xhdpi/images/loop00067.png
Binary files differ
diff --git a/res-xhdpi/images/loop00068.png b/res-xhdpi/images/loop00068.png
new file mode 100644
index 000000000..65d41a280
--- /dev/null
+++ b/res-xhdpi/images/loop00068.png
Binary files differ
diff --git a/res-xhdpi/images/loop00069.png b/res-xhdpi/images/loop00069.png
new file mode 100644
index 000000000..5707b62c7
--- /dev/null
+++ b/res-xhdpi/images/loop00069.png
Binary files differ
diff --git a/res-xhdpi/images/loop00070.png b/res-xhdpi/images/loop00070.png
new file mode 100644
index 000000000..50ea15925
--- /dev/null
+++ b/res-xhdpi/images/loop00070.png
Binary files differ
diff --git a/res-xhdpi/images/loop00071.png b/res-xhdpi/images/loop00071.png
new file mode 100644
index 000000000..244a91060
--- /dev/null
+++ b/res-xhdpi/images/loop00071.png
Binary files differ
diff --git a/res-xhdpi/images/loop00072.png b/res-xhdpi/images/loop00072.png
new file mode 100644
index 000000000..e5ee2abe7
--- /dev/null
+++ b/res-xhdpi/images/loop00072.png
Binary files differ
diff --git a/res-xhdpi/images/loop00073.png b/res-xhdpi/images/loop00073.png
new file mode 100644
index 000000000..fced739ae
--- /dev/null
+++ b/res-xhdpi/images/loop00073.png
Binary files differ
diff --git a/res-xhdpi/images/loop00074.png b/res-xhdpi/images/loop00074.png
new file mode 100644
index 000000000..1b739d346
--- /dev/null
+++ b/res-xhdpi/images/loop00074.png
Binary files differ
diff --git a/res-xhdpi/images/loop00075.png b/res-xhdpi/images/loop00075.png
new file mode 100644
index 000000000..989144f69
--- /dev/null
+++ b/res-xhdpi/images/loop00075.png
Binary files differ
diff --git a/res-xhdpi/images/loop00076.png b/res-xhdpi/images/loop00076.png
new file mode 100644
index 000000000..458c2a9a2
--- /dev/null
+++ b/res-xhdpi/images/loop00076.png
Binary files differ
diff --git a/res-xhdpi/images/loop00077.png b/res-xhdpi/images/loop00077.png
new file mode 100644
index 000000000..9cecb1d0d
--- /dev/null
+++ b/res-xhdpi/images/loop00077.png
Binary files differ
diff --git a/res-xhdpi/images/loop00078.png b/res-xhdpi/images/loop00078.png
new file mode 100644
index 000000000..c2c8dee86
--- /dev/null
+++ b/res-xhdpi/images/loop00078.png
Binary files differ
diff --git a/res-xhdpi/images/loop00079.png b/res-xhdpi/images/loop00079.png
new file mode 100644
index 000000000..4f4fdd142
--- /dev/null
+++ b/res-xhdpi/images/loop00079.png
Binary files differ
diff --git a/res-xhdpi/images/loop00080.png b/res-xhdpi/images/loop00080.png
new file mode 100644
index 000000000..b224378de
--- /dev/null
+++ b/res-xhdpi/images/loop00080.png
Binary files differ
diff --git a/res-xhdpi/images/loop00081.png b/res-xhdpi/images/loop00081.png
new file mode 100644
index 000000000..57d958755
--- /dev/null
+++ b/res-xhdpi/images/loop00081.png
Binary files differ
diff --git a/res-xhdpi/images/loop00082.png b/res-xhdpi/images/loop00082.png
new file mode 100644
index 000000000..c00f82a04
--- /dev/null
+++ b/res-xhdpi/images/loop00082.png
Binary files differ
diff --git a/res-xhdpi/images/loop00083.png b/res-xhdpi/images/loop00083.png
new file mode 100644
index 000000000..078311f09
--- /dev/null
+++ b/res-xhdpi/images/loop00083.png
Binary files differ
diff --git a/res-xhdpi/images/loop00084.png b/res-xhdpi/images/loop00084.png
new file mode 100644
index 000000000..cac170893
--- /dev/null
+++ b/res-xhdpi/images/loop00084.png
Binary files differ
diff --git a/res-xhdpi/images/loop00085.png b/res-xhdpi/images/loop00085.png
new file mode 100644
index 000000000..2ea4b0afc
--- /dev/null
+++ b/res-xhdpi/images/loop00085.png
Binary files differ
diff --git a/res-xhdpi/images/loop00086.png b/res-xhdpi/images/loop00086.png
new file mode 100644
index 000000000..9ba6ca615
--- /dev/null
+++ b/res-xhdpi/images/loop00086.png
Binary files differ
diff --git a/res-xhdpi/images/loop00087.png b/res-xhdpi/images/loop00087.png
new file mode 100644
index 000000000..75694a387
--- /dev/null
+++ b/res-xhdpi/images/loop00087.png
Binary files differ
diff --git a/res-xhdpi/images/loop00088.png b/res-xhdpi/images/loop00088.png
new file mode 100644
index 000000000..971e50848
--- /dev/null
+++ b/res-xhdpi/images/loop00088.png
Binary files differ
diff --git a/res-xhdpi/images/loop00089.png b/res-xhdpi/images/loop00089.png
new file mode 100644
index 000000000..41b6ce6b1
--- /dev/null
+++ b/res-xhdpi/images/loop00089.png
Binary files differ
diff --git a/res-xhdpi/images/loop00090.png b/res-xhdpi/images/loop00090.png
new file mode 100644
index 000000000..f5bf7a73b
--- /dev/null
+++ b/res-xhdpi/images/loop00090.png
Binary files differ
diff --git a/res-xhdpi/images/no_command_text.png b/res-xhdpi/images/no_command_text.png
index eb34e94b3..9f7403753 100644
--- a/res-xhdpi/images/no_command_text.png
+++ b/res-xhdpi/images/no_command_text.png
Binary files differ
diff --git a/res-xhdpi/images/progress_empty.png b/res-xhdpi/images/progress_empty.png
index 72581832c..96c4bf6b3 100644
--- a/res-xhdpi/images/progress_empty.png
+++ b/res-xhdpi/images/progress_empty.png
Binary files differ
diff --git a/res-xhdpi/images/progress_fill.png b/res-xhdpi/images/progress_fill.png
index becf87bdf..1717be820 100644
--- a/res-xhdpi/images/progress_fill.png
+++ b/res-xhdpi/images/progress_fill.png
Binary files differ
diff --git a/res-xxhdpi/images/erasing_text.png b/res-xxhdpi/images/erasing_text.png
index c87fd52b4..b8653eb95 100644
--- a/res-xxhdpi/images/erasing_text.png
+++ b/res-xxhdpi/images/erasing_text.png
Binary files differ
diff --git a/res-xxhdpi/images/error_text.png b/res-xxhdpi/images/error_text.png
index 486e951df..d77ee5085 100644
--- a/res-xxhdpi/images/error_text.png
+++ b/res-xxhdpi/images/error_text.png
Binary files differ
diff --git a/res-xxhdpi/images/icon_installing.png b/res-xxhdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc231..000000000
--- a/res-xxhdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-xxhdpi/images/installing_security_text.png b/res-xxhdpi/images/installing_security_text.png
new file mode 100644
index 000000000..ca0c191d4
--- /dev/null
+++ b/res-xxhdpi/images/installing_security_text.png
Binary files differ
diff --git a/res-xxhdpi/images/installing_text.png b/res-xxhdpi/images/installing_text.png
index ef6e8f3f0..a76a174f0 100644
--- a/res-xxhdpi/images/installing_text.png
+++ b/res-xxhdpi/images/installing_text.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00000.png b/res-xxhdpi/images/loop00000.png
new file mode 100644
index 000000000..c5172629d
--- /dev/null
+++ b/res-xxhdpi/images/loop00000.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00001.png b/res-xxhdpi/images/loop00001.png
new file mode 100644
index 000000000..1b1ce7397
--- /dev/null
+++ b/res-xxhdpi/images/loop00001.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00002.png b/res-xxhdpi/images/loop00002.png
new file mode 100644
index 000000000..e984a24c9
--- /dev/null
+++ b/res-xxhdpi/images/loop00002.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00003.png b/res-xxhdpi/images/loop00003.png
new file mode 100644
index 000000000..b11dddcb8
--- /dev/null
+++ b/res-xxhdpi/images/loop00003.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00004.png b/res-xxhdpi/images/loop00004.png
new file mode 100644
index 000000000..10272b271
--- /dev/null
+++ b/res-xxhdpi/images/loop00004.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00005.png b/res-xxhdpi/images/loop00005.png
new file mode 100644
index 000000000..9558d7e68
--- /dev/null
+++ b/res-xxhdpi/images/loop00005.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00006.png b/res-xxhdpi/images/loop00006.png
new file mode 100644
index 000000000..0e6c92d69
--- /dev/null
+++ b/res-xxhdpi/images/loop00006.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00007.png b/res-xxhdpi/images/loop00007.png
new file mode 100644
index 000000000..0a353ad02
--- /dev/null
+++ b/res-xxhdpi/images/loop00007.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00008.png b/res-xxhdpi/images/loop00008.png
new file mode 100644
index 000000000..2f0c1620c
--- /dev/null
+++ b/res-xxhdpi/images/loop00008.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00009.png b/res-xxhdpi/images/loop00009.png
new file mode 100644
index 000000000..960d683fa
--- /dev/null
+++ b/res-xxhdpi/images/loop00009.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00010.png b/res-xxhdpi/images/loop00010.png
new file mode 100644
index 000000000..b65c3011a
--- /dev/null
+++ b/res-xxhdpi/images/loop00010.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00011.png b/res-xxhdpi/images/loop00011.png
new file mode 100644
index 000000000..21444fa54
--- /dev/null
+++ b/res-xxhdpi/images/loop00011.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00012.png b/res-xxhdpi/images/loop00012.png
new file mode 100644
index 000000000..587db0990
--- /dev/null
+++ b/res-xxhdpi/images/loop00012.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00013.png b/res-xxhdpi/images/loop00013.png
new file mode 100644
index 000000000..57f2f66e2
--- /dev/null
+++ b/res-xxhdpi/images/loop00013.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00014.png b/res-xxhdpi/images/loop00014.png
new file mode 100644
index 000000000..d308a6530
--- /dev/null
+++ b/res-xxhdpi/images/loop00014.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00015.png b/res-xxhdpi/images/loop00015.png
new file mode 100644
index 000000000..3585facad
--- /dev/null
+++ b/res-xxhdpi/images/loop00015.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00016.png b/res-xxhdpi/images/loop00016.png
new file mode 100644
index 000000000..fd5089c44
--- /dev/null
+++ b/res-xxhdpi/images/loop00016.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00017.png b/res-xxhdpi/images/loop00017.png
new file mode 100644
index 000000000..2c8c6a434
--- /dev/null
+++ b/res-xxhdpi/images/loop00017.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00018.png b/res-xxhdpi/images/loop00018.png
new file mode 100644
index 000000000..23d7ca287
--- /dev/null
+++ b/res-xxhdpi/images/loop00018.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00019.png b/res-xxhdpi/images/loop00019.png
new file mode 100644
index 000000000..cdefe2c55
--- /dev/null
+++ b/res-xxhdpi/images/loop00019.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00020.png b/res-xxhdpi/images/loop00020.png
new file mode 100644
index 000000000..ae78e4cfe
--- /dev/null
+++ b/res-xxhdpi/images/loop00020.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00021.png b/res-xxhdpi/images/loop00021.png
new file mode 100644
index 000000000..ad83cfe04
--- /dev/null
+++ b/res-xxhdpi/images/loop00021.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00022.png b/res-xxhdpi/images/loop00022.png
new file mode 100644
index 000000000..850076ac1
--- /dev/null
+++ b/res-xxhdpi/images/loop00022.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00023.png b/res-xxhdpi/images/loop00023.png
new file mode 100644
index 000000000..cd30b3997
--- /dev/null
+++ b/res-xxhdpi/images/loop00023.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00024.png b/res-xxhdpi/images/loop00024.png
new file mode 100644
index 000000000..e7ae4b277
--- /dev/null
+++ b/res-xxhdpi/images/loop00024.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00025.png b/res-xxhdpi/images/loop00025.png
new file mode 100644
index 000000000..4e24bd118
--- /dev/null
+++ b/res-xxhdpi/images/loop00025.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00026.png b/res-xxhdpi/images/loop00026.png
new file mode 100644
index 000000000..27713cce9
--- /dev/null
+++ b/res-xxhdpi/images/loop00026.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00027.png b/res-xxhdpi/images/loop00027.png
new file mode 100644
index 000000000..34e4ade2e
--- /dev/null
+++ b/res-xxhdpi/images/loop00027.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00028.png b/res-xxhdpi/images/loop00028.png
new file mode 100644
index 000000000..0e6fdee75
--- /dev/null
+++ b/res-xxhdpi/images/loop00028.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00029.png b/res-xxhdpi/images/loop00029.png
new file mode 100644
index 000000000..21c1c635b
--- /dev/null
+++ b/res-xxhdpi/images/loop00029.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00030.png b/res-xxhdpi/images/loop00030.png
new file mode 100644
index 000000000..984c24f9b
--- /dev/null
+++ b/res-xxhdpi/images/loop00030.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00031.png b/res-xxhdpi/images/loop00031.png
new file mode 100644
index 000000000..25fe1de26
--- /dev/null
+++ b/res-xxhdpi/images/loop00031.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00032.png b/res-xxhdpi/images/loop00032.png
new file mode 100644
index 000000000..c089cb8a4
--- /dev/null
+++ b/res-xxhdpi/images/loop00032.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00033.png b/res-xxhdpi/images/loop00033.png
new file mode 100644
index 000000000..82a2d9b54
--- /dev/null
+++ b/res-xxhdpi/images/loop00033.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00034.png b/res-xxhdpi/images/loop00034.png
new file mode 100644
index 000000000..1aa76b94c
--- /dev/null
+++ b/res-xxhdpi/images/loop00034.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00035.png b/res-xxhdpi/images/loop00035.png
new file mode 100644
index 000000000..4399143e4
--- /dev/null
+++ b/res-xxhdpi/images/loop00035.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00036.png b/res-xxhdpi/images/loop00036.png
new file mode 100644
index 000000000..975ae666e
--- /dev/null
+++ b/res-xxhdpi/images/loop00036.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00037.png b/res-xxhdpi/images/loop00037.png
new file mode 100644
index 000000000..dcf9a9050
--- /dev/null
+++ b/res-xxhdpi/images/loop00037.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00038.png b/res-xxhdpi/images/loop00038.png
new file mode 100644
index 000000000..f10b8b723
--- /dev/null
+++ b/res-xxhdpi/images/loop00038.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00039.png b/res-xxhdpi/images/loop00039.png
new file mode 100644
index 000000000..9c0d1e361
--- /dev/null
+++ b/res-xxhdpi/images/loop00039.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00040.png b/res-xxhdpi/images/loop00040.png
new file mode 100644
index 000000000..b6b4908f6
--- /dev/null
+++ b/res-xxhdpi/images/loop00040.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00041.png b/res-xxhdpi/images/loop00041.png
new file mode 100644
index 000000000..12a1a1e9a
--- /dev/null
+++ b/res-xxhdpi/images/loop00041.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00042.png b/res-xxhdpi/images/loop00042.png
new file mode 100644
index 000000000..f1fc35baf
--- /dev/null
+++ b/res-xxhdpi/images/loop00042.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00043.png b/res-xxhdpi/images/loop00043.png
new file mode 100644
index 000000000..50ac99e5e
--- /dev/null
+++ b/res-xxhdpi/images/loop00043.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00044.png b/res-xxhdpi/images/loop00044.png
new file mode 100644
index 000000000..f115dcc9b
--- /dev/null
+++ b/res-xxhdpi/images/loop00044.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00045.png b/res-xxhdpi/images/loop00045.png
new file mode 100644
index 000000000..adf7a671e
--- /dev/null
+++ b/res-xxhdpi/images/loop00045.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00046.png b/res-xxhdpi/images/loop00046.png
new file mode 100644
index 000000000..588eeb3fb
--- /dev/null
+++ b/res-xxhdpi/images/loop00046.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00047.png b/res-xxhdpi/images/loop00047.png
new file mode 100644
index 000000000..9dea7701d
--- /dev/null
+++ b/res-xxhdpi/images/loop00047.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00048.png b/res-xxhdpi/images/loop00048.png
new file mode 100644
index 000000000..d5eaeb126
--- /dev/null
+++ b/res-xxhdpi/images/loop00048.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00049.png b/res-xxhdpi/images/loop00049.png
new file mode 100644
index 000000000..fb837295b
--- /dev/null
+++ b/res-xxhdpi/images/loop00049.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00050.png b/res-xxhdpi/images/loop00050.png
new file mode 100644
index 000000000..72441db4f
--- /dev/null
+++ b/res-xxhdpi/images/loop00050.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00051.png b/res-xxhdpi/images/loop00051.png
new file mode 100644
index 000000000..bf7170a53
--- /dev/null
+++ b/res-xxhdpi/images/loop00051.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00052.png b/res-xxhdpi/images/loop00052.png
new file mode 100644
index 000000000..c512b56d4
--- /dev/null
+++ b/res-xxhdpi/images/loop00052.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00053.png b/res-xxhdpi/images/loop00053.png
new file mode 100644
index 000000000..6ac3ca6f3
--- /dev/null
+++ b/res-xxhdpi/images/loop00053.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00054.png b/res-xxhdpi/images/loop00054.png
new file mode 100644
index 000000000..ba194a6ad
--- /dev/null
+++ b/res-xxhdpi/images/loop00054.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00055.png b/res-xxhdpi/images/loop00055.png
new file mode 100644
index 000000000..9623f0d5c
--- /dev/null
+++ b/res-xxhdpi/images/loop00055.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00056.png b/res-xxhdpi/images/loop00056.png
new file mode 100644
index 000000000..e785e690f
--- /dev/null
+++ b/res-xxhdpi/images/loop00056.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00057.png b/res-xxhdpi/images/loop00057.png
new file mode 100644
index 000000000..9a5747ae3
--- /dev/null
+++ b/res-xxhdpi/images/loop00057.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00058.png b/res-xxhdpi/images/loop00058.png
new file mode 100644
index 000000000..9a097cf12
--- /dev/null
+++ b/res-xxhdpi/images/loop00058.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00059.png b/res-xxhdpi/images/loop00059.png
new file mode 100644
index 000000000..fee2db1e1
--- /dev/null
+++ b/res-xxhdpi/images/loop00059.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00060.png b/res-xxhdpi/images/loop00060.png
new file mode 100644
index 000000000..0e00e709f
--- /dev/null
+++ b/res-xxhdpi/images/loop00060.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00061.png b/res-xxhdpi/images/loop00061.png
new file mode 100644
index 000000000..0ecce17bd
--- /dev/null
+++ b/res-xxhdpi/images/loop00061.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00062.png b/res-xxhdpi/images/loop00062.png
new file mode 100644
index 000000000..0a296d129
--- /dev/null
+++ b/res-xxhdpi/images/loop00062.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00063.png b/res-xxhdpi/images/loop00063.png
new file mode 100644
index 000000000..56c3b8b9b
--- /dev/null
+++ b/res-xxhdpi/images/loop00063.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00064.png b/res-xxhdpi/images/loop00064.png
new file mode 100644
index 000000000..e6d639a3d
--- /dev/null
+++ b/res-xxhdpi/images/loop00064.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00065.png b/res-xxhdpi/images/loop00065.png
new file mode 100644
index 000000000..02e382b99
--- /dev/null
+++ b/res-xxhdpi/images/loop00065.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00066.png b/res-xxhdpi/images/loop00066.png
new file mode 100644
index 000000000..fe89ed00a
--- /dev/null
+++ b/res-xxhdpi/images/loop00066.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00067.png b/res-xxhdpi/images/loop00067.png
new file mode 100644
index 000000000..a8f6ce50c
--- /dev/null
+++ b/res-xxhdpi/images/loop00067.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00068.png b/res-xxhdpi/images/loop00068.png
new file mode 100644
index 000000000..f9b7fb1c9
--- /dev/null
+++ b/res-xxhdpi/images/loop00068.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00069.png b/res-xxhdpi/images/loop00069.png
new file mode 100644
index 000000000..d0dc50768
--- /dev/null
+++ b/res-xxhdpi/images/loop00069.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00070.png b/res-xxhdpi/images/loop00070.png
new file mode 100644
index 000000000..63f9e4df1
--- /dev/null
+++ b/res-xxhdpi/images/loop00070.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00071.png b/res-xxhdpi/images/loop00071.png
new file mode 100644
index 000000000..5ba39724f
--- /dev/null
+++ b/res-xxhdpi/images/loop00071.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00072.png b/res-xxhdpi/images/loop00072.png
new file mode 100644
index 000000000..de834e398
--- /dev/null
+++ b/res-xxhdpi/images/loop00072.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00073.png b/res-xxhdpi/images/loop00073.png
new file mode 100644
index 000000000..4be2aed88
--- /dev/null
+++ b/res-xxhdpi/images/loop00073.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00074.png b/res-xxhdpi/images/loop00074.png
new file mode 100644
index 000000000..235e9a228
--- /dev/null
+++ b/res-xxhdpi/images/loop00074.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00075.png b/res-xxhdpi/images/loop00075.png
new file mode 100644
index 000000000..f6d806d5a
--- /dev/null
+++ b/res-xxhdpi/images/loop00075.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00076.png b/res-xxhdpi/images/loop00076.png
new file mode 100644
index 000000000..1e916d723
--- /dev/null
+++ b/res-xxhdpi/images/loop00076.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00077.png b/res-xxhdpi/images/loop00077.png
new file mode 100644
index 000000000..0dbac748e
--- /dev/null
+++ b/res-xxhdpi/images/loop00077.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00078.png b/res-xxhdpi/images/loop00078.png
new file mode 100644
index 000000000..504d34a44
--- /dev/null
+++ b/res-xxhdpi/images/loop00078.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00079.png b/res-xxhdpi/images/loop00079.png
new file mode 100644
index 000000000..51f4e8d7c
--- /dev/null
+++ b/res-xxhdpi/images/loop00079.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00080.png b/res-xxhdpi/images/loop00080.png
new file mode 100644
index 000000000..6ef03b82e
--- /dev/null
+++ b/res-xxhdpi/images/loop00080.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00081.png b/res-xxhdpi/images/loop00081.png
new file mode 100644
index 000000000..e2ebc394d
--- /dev/null
+++ b/res-xxhdpi/images/loop00081.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00082.png b/res-xxhdpi/images/loop00082.png
new file mode 100644
index 000000000..9de83a733
--- /dev/null
+++ b/res-xxhdpi/images/loop00082.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00083.png b/res-xxhdpi/images/loop00083.png
new file mode 100644
index 000000000..c5c0099de
--- /dev/null
+++ b/res-xxhdpi/images/loop00083.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00084.png b/res-xxhdpi/images/loop00084.png
new file mode 100644
index 000000000..84c794f31
--- /dev/null
+++ b/res-xxhdpi/images/loop00084.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00085.png b/res-xxhdpi/images/loop00085.png
new file mode 100644
index 000000000..29a40c628
--- /dev/null
+++ b/res-xxhdpi/images/loop00085.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00086.png b/res-xxhdpi/images/loop00086.png
new file mode 100644
index 000000000..89a471735
--- /dev/null
+++ b/res-xxhdpi/images/loop00086.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00087.png b/res-xxhdpi/images/loop00087.png
new file mode 100644
index 000000000..ef8d4d5db
--- /dev/null
+++ b/res-xxhdpi/images/loop00087.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00088.png b/res-xxhdpi/images/loop00088.png
new file mode 100644
index 000000000..5fc6c6224
--- /dev/null
+++ b/res-xxhdpi/images/loop00088.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00089.png b/res-xxhdpi/images/loop00089.png
new file mode 100644
index 000000000..d6d99f42f
--- /dev/null
+++ b/res-xxhdpi/images/loop00089.png
Binary files differ
diff --git a/res-xxhdpi/images/loop00090.png b/res-xxhdpi/images/loop00090.png
new file mode 100644
index 000000000..c5172629d
--- /dev/null
+++ b/res-xxhdpi/images/loop00090.png
Binary files differ
diff --git a/res-xxhdpi/images/no_command_text.png b/res-xxhdpi/images/no_command_text.png
index cc98bb18a..5e363e3a5 100644
--- a/res-xxhdpi/images/no_command_text.png
+++ b/res-xxhdpi/images/no_command_text.png
Binary files differ
diff --git a/res-xxhdpi/images/progress_empty.png b/res-xxhdpi/images/progress_empty.png
index 72581832c..96c4bf6b3 100644
--- a/res-xxhdpi/images/progress_empty.png
+++ b/res-xxhdpi/images/progress_empty.png
Binary files differ
diff --git a/res-xxhdpi/images/progress_fill.png b/res-xxhdpi/images/progress_fill.png
index becf87bdf..1717be820 100644
--- a/res-xxhdpi/images/progress_fill.png
+++ b/res-xxhdpi/images/progress_fill.png
Binary files differ
diff --git a/res-xxxhdpi/images/erasing_text.png b/res-xxxhdpi/images/erasing_text.png
index 612e7a390..f4a466118 100644
--- a/res-xxxhdpi/images/erasing_text.png
+++ b/res-xxxhdpi/images/erasing_text.png
Binary files differ
diff --git a/res-xxxhdpi/images/error_text.png b/res-xxxhdpi/images/error_text.png
index 50d2fadb5..317a7716f 100644
--- a/res-xxxhdpi/images/error_text.png
+++ b/res-xxxhdpi/images/error_text.png
Binary files differ
diff --git a/res-xxxhdpi/images/icon_installing.png b/res-xxxhdpi/images/icon_installing.png
deleted file mode 100644
index 0fcfbc231..000000000
--- a/res-xxxhdpi/images/icon_installing.png
+++ /dev/null
Binary files differ
diff --git a/res-xxxhdpi/images/installing_security_text.png b/res-xxxhdpi/images/installing_security_text.png
new file mode 100644
index 000000000..c99c9072a
--- /dev/null
+++ b/res-xxxhdpi/images/installing_security_text.png
Binary files differ
diff --git a/res-xxxhdpi/images/installing_text.png b/res-xxxhdpi/images/installing_text.png
index 9bd093bf4..91d833017 100644
--- a/res-xxxhdpi/images/installing_text.png
+++ b/res-xxxhdpi/images/installing_text.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00000.png b/res-xxxhdpi/images/loop00000.png
new file mode 100644
index 000000000..1bc9db5b1
--- /dev/null
+++ b/res-xxxhdpi/images/loop00000.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00001.png b/res-xxxhdpi/images/loop00001.png
new file mode 100644
index 000000000..f835b8567
--- /dev/null
+++ b/res-xxxhdpi/images/loop00001.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00002.png b/res-xxxhdpi/images/loop00002.png
new file mode 100644
index 000000000..e3bff326c
--- /dev/null
+++ b/res-xxxhdpi/images/loop00002.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00003.png b/res-xxxhdpi/images/loop00003.png
new file mode 100644
index 000000000..d864c15d7
--- /dev/null
+++ b/res-xxxhdpi/images/loop00003.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00004.png b/res-xxxhdpi/images/loop00004.png
new file mode 100644
index 000000000..5d861c9b4
--- /dev/null
+++ b/res-xxxhdpi/images/loop00004.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00005.png b/res-xxxhdpi/images/loop00005.png
new file mode 100644
index 000000000..e9e860c3c
--- /dev/null
+++ b/res-xxxhdpi/images/loop00005.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00006.png b/res-xxxhdpi/images/loop00006.png
new file mode 100644
index 000000000..d7c516e52
--- /dev/null
+++ b/res-xxxhdpi/images/loop00006.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00007.png b/res-xxxhdpi/images/loop00007.png
new file mode 100644
index 000000000..fa6d39716
--- /dev/null
+++ b/res-xxxhdpi/images/loop00007.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00008.png b/res-xxxhdpi/images/loop00008.png
new file mode 100644
index 000000000..888d3a278
--- /dev/null
+++ b/res-xxxhdpi/images/loop00008.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00009.png b/res-xxxhdpi/images/loop00009.png
new file mode 100644
index 000000000..9e6ead241
--- /dev/null
+++ b/res-xxxhdpi/images/loop00009.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00010.png b/res-xxxhdpi/images/loop00010.png
new file mode 100644
index 000000000..30e13e058
--- /dev/null
+++ b/res-xxxhdpi/images/loop00010.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00011.png b/res-xxxhdpi/images/loop00011.png
new file mode 100644
index 000000000..d8abc2bb5
--- /dev/null
+++ b/res-xxxhdpi/images/loop00011.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00012.png b/res-xxxhdpi/images/loop00012.png
new file mode 100644
index 000000000..2d88cfb6a
--- /dev/null
+++ b/res-xxxhdpi/images/loop00012.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00013.png b/res-xxxhdpi/images/loop00013.png
new file mode 100644
index 000000000..0250f7494
--- /dev/null
+++ b/res-xxxhdpi/images/loop00013.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00014.png b/res-xxxhdpi/images/loop00014.png
new file mode 100644
index 000000000..c3d9239c9
--- /dev/null
+++ b/res-xxxhdpi/images/loop00014.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00015.png b/res-xxxhdpi/images/loop00015.png
new file mode 100644
index 000000000..644c9c6bd
--- /dev/null
+++ b/res-xxxhdpi/images/loop00015.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00016.png b/res-xxxhdpi/images/loop00016.png
new file mode 100644
index 000000000..eff6e5b4e
--- /dev/null
+++ b/res-xxxhdpi/images/loop00016.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00017.png b/res-xxxhdpi/images/loop00017.png
new file mode 100644
index 000000000..b472a86be
--- /dev/null
+++ b/res-xxxhdpi/images/loop00017.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00018.png b/res-xxxhdpi/images/loop00018.png
new file mode 100644
index 000000000..b17b6ce12
--- /dev/null
+++ b/res-xxxhdpi/images/loop00018.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00019.png b/res-xxxhdpi/images/loop00019.png
new file mode 100644
index 000000000..d89b4da52
--- /dev/null
+++ b/res-xxxhdpi/images/loop00019.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00020.png b/res-xxxhdpi/images/loop00020.png
new file mode 100644
index 000000000..7e757b845
--- /dev/null
+++ b/res-xxxhdpi/images/loop00020.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00021.png b/res-xxxhdpi/images/loop00021.png
new file mode 100644
index 000000000..1a8ce3ec5
--- /dev/null
+++ b/res-xxxhdpi/images/loop00021.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00022.png b/res-xxxhdpi/images/loop00022.png
new file mode 100644
index 000000000..e9ab39a5f
--- /dev/null
+++ b/res-xxxhdpi/images/loop00022.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00023.png b/res-xxxhdpi/images/loop00023.png
new file mode 100644
index 000000000..e1a7bf782
--- /dev/null
+++ b/res-xxxhdpi/images/loop00023.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00024.png b/res-xxxhdpi/images/loop00024.png
new file mode 100644
index 000000000..f77f70cff
--- /dev/null
+++ b/res-xxxhdpi/images/loop00024.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00025.png b/res-xxxhdpi/images/loop00025.png
new file mode 100644
index 000000000..8348cdfca
--- /dev/null
+++ b/res-xxxhdpi/images/loop00025.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00026.png b/res-xxxhdpi/images/loop00026.png
new file mode 100644
index 000000000..55fecc8bb
--- /dev/null
+++ b/res-xxxhdpi/images/loop00026.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00027.png b/res-xxxhdpi/images/loop00027.png
new file mode 100644
index 000000000..f4edf0641
--- /dev/null
+++ b/res-xxxhdpi/images/loop00027.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00028.png b/res-xxxhdpi/images/loop00028.png
new file mode 100644
index 000000000..6dbe90446
--- /dev/null
+++ b/res-xxxhdpi/images/loop00028.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00029.png b/res-xxxhdpi/images/loop00029.png
new file mode 100644
index 000000000..764f27a05
--- /dev/null
+++ b/res-xxxhdpi/images/loop00029.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00030.png b/res-xxxhdpi/images/loop00030.png
new file mode 100644
index 000000000..2d2156930
--- /dev/null
+++ b/res-xxxhdpi/images/loop00030.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00031.png b/res-xxxhdpi/images/loop00031.png
new file mode 100644
index 000000000..e02db9c8b
--- /dev/null
+++ b/res-xxxhdpi/images/loop00031.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00032.png b/res-xxxhdpi/images/loop00032.png
new file mode 100644
index 000000000..03f045684
--- /dev/null
+++ b/res-xxxhdpi/images/loop00032.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00033.png b/res-xxxhdpi/images/loop00033.png
new file mode 100644
index 000000000..5bdbbdbaf
--- /dev/null
+++ b/res-xxxhdpi/images/loop00033.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00034.png b/res-xxxhdpi/images/loop00034.png
new file mode 100644
index 000000000..c8164e204
--- /dev/null
+++ b/res-xxxhdpi/images/loop00034.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00035.png b/res-xxxhdpi/images/loop00035.png
new file mode 100644
index 000000000..ed5721d7c
--- /dev/null
+++ b/res-xxxhdpi/images/loop00035.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00036.png b/res-xxxhdpi/images/loop00036.png
new file mode 100644
index 000000000..08dffd26b
--- /dev/null
+++ b/res-xxxhdpi/images/loop00036.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00037.png b/res-xxxhdpi/images/loop00037.png
new file mode 100644
index 000000000..583b665e4
--- /dev/null
+++ b/res-xxxhdpi/images/loop00037.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00038.png b/res-xxxhdpi/images/loop00038.png
new file mode 100644
index 000000000..cc2933d6a
--- /dev/null
+++ b/res-xxxhdpi/images/loop00038.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00039.png b/res-xxxhdpi/images/loop00039.png
new file mode 100644
index 000000000..1f0496adb
--- /dev/null
+++ b/res-xxxhdpi/images/loop00039.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00040.png b/res-xxxhdpi/images/loop00040.png
new file mode 100644
index 000000000..05bf33593
--- /dev/null
+++ b/res-xxxhdpi/images/loop00040.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00041.png b/res-xxxhdpi/images/loop00041.png
new file mode 100644
index 000000000..a868c7b2d
--- /dev/null
+++ b/res-xxxhdpi/images/loop00041.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00042.png b/res-xxxhdpi/images/loop00042.png
new file mode 100644
index 000000000..7c7220f29
--- /dev/null
+++ b/res-xxxhdpi/images/loop00042.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00043.png b/res-xxxhdpi/images/loop00043.png
new file mode 100644
index 000000000..30336a77b
--- /dev/null
+++ b/res-xxxhdpi/images/loop00043.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00044.png b/res-xxxhdpi/images/loop00044.png
new file mode 100644
index 000000000..80d373584
--- /dev/null
+++ b/res-xxxhdpi/images/loop00044.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00045.png b/res-xxxhdpi/images/loop00045.png
new file mode 100644
index 000000000..71a52c20c
--- /dev/null
+++ b/res-xxxhdpi/images/loop00045.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00046.png b/res-xxxhdpi/images/loop00046.png
new file mode 100644
index 000000000..b3b37029d
--- /dev/null
+++ b/res-xxxhdpi/images/loop00046.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00047.png b/res-xxxhdpi/images/loop00047.png
new file mode 100644
index 000000000..6ce2b37ab
--- /dev/null
+++ b/res-xxxhdpi/images/loop00047.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00048.png b/res-xxxhdpi/images/loop00048.png
new file mode 100644
index 000000000..0b428cd73
--- /dev/null
+++ b/res-xxxhdpi/images/loop00048.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00049.png b/res-xxxhdpi/images/loop00049.png
new file mode 100644
index 000000000..53c1a4774
--- /dev/null
+++ b/res-xxxhdpi/images/loop00049.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00050.png b/res-xxxhdpi/images/loop00050.png
new file mode 100644
index 000000000..0e17bbdff
--- /dev/null
+++ b/res-xxxhdpi/images/loop00050.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00051.png b/res-xxxhdpi/images/loop00051.png
new file mode 100644
index 000000000..78a99dcc7
--- /dev/null
+++ b/res-xxxhdpi/images/loop00051.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00052.png b/res-xxxhdpi/images/loop00052.png
new file mode 100644
index 000000000..efd0df559
--- /dev/null
+++ b/res-xxxhdpi/images/loop00052.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00053.png b/res-xxxhdpi/images/loop00053.png
new file mode 100644
index 000000000..0c417eef9
--- /dev/null
+++ b/res-xxxhdpi/images/loop00053.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00054.png b/res-xxxhdpi/images/loop00054.png
new file mode 100644
index 000000000..072077e6f
--- /dev/null
+++ b/res-xxxhdpi/images/loop00054.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00055.png b/res-xxxhdpi/images/loop00055.png
new file mode 100644
index 000000000..693083ac8
--- /dev/null
+++ b/res-xxxhdpi/images/loop00055.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00056.png b/res-xxxhdpi/images/loop00056.png
new file mode 100644
index 000000000..07cbd75d1
--- /dev/null
+++ b/res-xxxhdpi/images/loop00056.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00057.png b/res-xxxhdpi/images/loop00057.png
new file mode 100644
index 000000000..cc98ab21a
--- /dev/null
+++ b/res-xxxhdpi/images/loop00057.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00058.png b/res-xxxhdpi/images/loop00058.png
new file mode 100644
index 000000000..f55d21821
--- /dev/null
+++ b/res-xxxhdpi/images/loop00058.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00059.png b/res-xxxhdpi/images/loop00059.png
new file mode 100644
index 000000000..4bfed350a
--- /dev/null
+++ b/res-xxxhdpi/images/loop00059.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00060.png b/res-xxxhdpi/images/loop00060.png
new file mode 100644
index 000000000..59f158b10
--- /dev/null
+++ b/res-xxxhdpi/images/loop00060.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00061.png b/res-xxxhdpi/images/loop00061.png
new file mode 100644
index 000000000..fd0dc558d
--- /dev/null
+++ b/res-xxxhdpi/images/loop00061.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00062.png b/res-xxxhdpi/images/loop00062.png
new file mode 100644
index 000000000..2c316ce69
--- /dev/null
+++ b/res-xxxhdpi/images/loop00062.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00063.png b/res-xxxhdpi/images/loop00063.png
new file mode 100644
index 000000000..5b83c81cd
--- /dev/null
+++ b/res-xxxhdpi/images/loop00063.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00064.png b/res-xxxhdpi/images/loop00064.png
new file mode 100644
index 000000000..ced0a9ab5
--- /dev/null
+++ b/res-xxxhdpi/images/loop00064.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00065.png b/res-xxxhdpi/images/loop00065.png
new file mode 100644
index 000000000..6e699dda6
--- /dev/null
+++ b/res-xxxhdpi/images/loop00065.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00066.png b/res-xxxhdpi/images/loop00066.png
new file mode 100644
index 000000000..8853cfffe
--- /dev/null
+++ b/res-xxxhdpi/images/loop00066.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00067.png b/res-xxxhdpi/images/loop00067.png
new file mode 100644
index 000000000..24d11d14b
--- /dev/null
+++ b/res-xxxhdpi/images/loop00067.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00068.png b/res-xxxhdpi/images/loop00068.png
new file mode 100644
index 000000000..d54fff0ba
--- /dev/null
+++ b/res-xxxhdpi/images/loop00068.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00069.png b/res-xxxhdpi/images/loop00069.png
new file mode 100644
index 000000000..67f8d7884
--- /dev/null
+++ b/res-xxxhdpi/images/loop00069.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00070.png b/res-xxxhdpi/images/loop00070.png
new file mode 100644
index 000000000..d56fb78a5
--- /dev/null
+++ b/res-xxxhdpi/images/loop00070.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00071.png b/res-xxxhdpi/images/loop00071.png
new file mode 100644
index 000000000..e787b8a5a
--- /dev/null
+++ b/res-xxxhdpi/images/loop00071.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00072.png b/res-xxxhdpi/images/loop00072.png
new file mode 100644
index 000000000..81f2e4c4b
--- /dev/null
+++ b/res-xxxhdpi/images/loop00072.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00073.png b/res-xxxhdpi/images/loop00073.png
new file mode 100644
index 000000000..ad46ed162
--- /dev/null
+++ b/res-xxxhdpi/images/loop00073.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00074.png b/res-xxxhdpi/images/loop00074.png
new file mode 100644
index 000000000..d835a2bd3
--- /dev/null
+++ b/res-xxxhdpi/images/loop00074.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00075.png b/res-xxxhdpi/images/loop00075.png
new file mode 100644
index 000000000..aa35a84ba
--- /dev/null
+++ b/res-xxxhdpi/images/loop00075.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00076.png b/res-xxxhdpi/images/loop00076.png
new file mode 100644
index 000000000..6ea547e29
--- /dev/null
+++ b/res-xxxhdpi/images/loop00076.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00077.png b/res-xxxhdpi/images/loop00077.png
new file mode 100644
index 000000000..c80938309
--- /dev/null
+++ b/res-xxxhdpi/images/loop00077.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00078.png b/res-xxxhdpi/images/loop00078.png
new file mode 100644
index 000000000..827a75c9f
--- /dev/null
+++ b/res-xxxhdpi/images/loop00078.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00079.png b/res-xxxhdpi/images/loop00079.png
new file mode 100644
index 000000000..18dc1cf90
--- /dev/null
+++ b/res-xxxhdpi/images/loop00079.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00080.png b/res-xxxhdpi/images/loop00080.png
new file mode 100644
index 000000000..df06b5628
--- /dev/null
+++ b/res-xxxhdpi/images/loop00080.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00081.png b/res-xxxhdpi/images/loop00081.png
new file mode 100644
index 000000000..a5ba60379
--- /dev/null
+++ b/res-xxxhdpi/images/loop00081.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00082.png b/res-xxxhdpi/images/loop00082.png
new file mode 100644
index 000000000..e3298c5f3
--- /dev/null
+++ b/res-xxxhdpi/images/loop00082.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00083.png b/res-xxxhdpi/images/loop00083.png
new file mode 100644
index 000000000..c395662c4
--- /dev/null
+++ b/res-xxxhdpi/images/loop00083.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00084.png b/res-xxxhdpi/images/loop00084.png
new file mode 100644
index 000000000..f80af8e78
--- /dev/null
+++ b/res-xxxhdpi/images/loop00084.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00085.png b/res-xxxhdpi/images/loop00085.png
new file mode 100644
index 000000000..c89675830
--- /dev/null
+++ b/res-xxxhdpi/images/loop00085.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00086.png b/res-xxxhdpi/images/loop00086.png
new file mode 100644
index 000000000..97716923f
--- /dev/null
+++ b/res-xxxhdpi/images/loop00086.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00087.png b/res-xxxhdpi/images/loop00087.png
new file mode 100644
index 000000000..e805dfa01
--- /dev/null
+++ b/res-xxxhdpi/images/loop00087.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00088.png b/res-xxxhdpi/images/loop00088.png
new file mode 100644
index 000000000..aa1a88e26
--- /dev/null
+++ b/res-xxxhdpi/images/loop00088.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00089.png b/res-xxxhdpi/images/loop00089.png
new file mode 100644
index 000000000..5bf7781d0
--- /dev/null
+++ b/res-xxxhdpi/images/loop00089.png
Binary files differ
diff --git a/res-xxxhdpi/images/loop00090.png b/res-xxxhdpi/images/loop00090.png
new file mode 100644
index 000000000..1bc9db5b1
--- /dev/null
+++ b/res-xxxhdpi/images/loop00090.png
Binary files differ
diff --git a/res-xxxhdpi/images/no_command_text.png b/res-xxxhdpi/images/no_command_text.png
index 6354e6a99..b6eb964ba 100644
--- a/res-xxxhdpi/images/no_command_text.png
+++ b/res-xxxhdpi/images/no_command_text.png
Binary files differ
diff --git a/res-xxxhdpi/images/progress_empty.png b/res-xxxhdpi/images/progress_empty.png
index 72581832c..96c4bf6b3 100644
--- a/res-xxxhdpi/images/progress_empty.png
+++ b/res-xxxhdpi/images/progress_empty.png
Binary files differ
diff --git a/res-xxxhdpi/images/progress_fill.png b/res-xxxhdpi/images/progress_fill.png
index becf87bdf..1717be820 100644
--- a/res-xxxhdpi/images/progress_fill.png
+++ b/res-xxxhdpi/images/progress_fill.png
Binary files differ
diff --git a/roots.cpp b/roots.cpp
index 12c6b5ee2..f361cb8ca 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -175,7 +175,7 @@ static int exec_cmd(const char* path, char* const argv[]) {
return WEXITSTATUS(status);
}
-int format_volume(const char* volume) {
+int format_volume(const char* volume, const char* directory) {
Volume* v = volume_for_path(volume);
if (v == NULL) {
LOGE("unknown volume \"%s\"\n", volume);
@@ -241,7 +241,7 @@ int format_volume(const char* volume) {
}
int result;
if (strcmp(v->fs_type, "ext4") == 0) {
- result = make_ext4fs(v->blk_device, length, volume, sehandle);
+ result = make_ext4fs_directory(v->blk_device, length, volume, sehandle, directory);
} else { /* Has to be f2fs because we checked earlier. */
if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0 && length < 0) {
LOGE("format_volume: crypt footer + negative length (%zd) not supported on %s\n", length, v->fs_type);
@@ -273,6 +273,10 @@ int format_volume(const char* volume) {
return -1;
}
+int format_volume(const char* volume) {
+ return format_volume(volume, NULL);
+}
+
int setup_install_mounts() {
if (fstab == NULL) {
LOGE("can't set up install mounts: no fstab loaded\n");
diff --git a/roots.h b/roots.h
index 6e3b24355..a14b7d971 100644
--- a/roots.h
+++ b/roots.h
@@ -41,6 +41,12 @@ int ensure_path_unmounted(const char* path);
// it is mounted.
int format_volume(const char* volume);
+// Reformat the given volume (must be the mount point only, eg
+// "/cache"), no paths permitted. Attempts to unmount the volume if
+// it is mounted.
+// Copies 'directory' to root of the newly formatted volume
+int format_volume(const char* volume, const char* directory);
+
// Ensure that all and only the volumes that packages expect to find
// mounted (/tmp and /cache) are mounted. Returns 0 on success.
int setup_install_mounts();
diff --git a/screen_ui.cpp b/screen_ui.cpp
index 1d33269d2..369755438 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
@@ -40,8 +41,7 @@
#include "screen_ui.h"
#include "ui.h"
-static int char_width;
-static int char_height;
+#define TEXT_INDENT 4
// Return the current time as a double (including fractions of a second).
static double now() {
@@ -52,9 +52,9 @@ static double now() {
ScreenRecoveryUI::ScreenRecoveryUI() :
currentIcon(NONE),
- installingFrame(0),
locale(nullptr),
- rtl_locale(false),
+ intro_done(false),
+ current_frame(0),
progressBarType(EMPTY),
progressScopeStart(0),
progressScopeSize(0),
@@ -73,83 +73,114 @@ ScreenRecoveryUI::ScreenRecoveryUI() :
menu_items(0),
menu_sel(0),
file_viewer_text_(nullptr),
- animation_fps(-1),
- installing_frames(-1),
+ intro_frames(0),
+ loop_frames(0),
+ animation_fps(30), // TODO: there's currently no way to infer this.
stage(-1),
- max_stage(-1) {
+ max_stage(-1),
+ updateMutex(PTHREAD_MUTEX_INITIALIZER),
+ rtl_locale(false) {
+}
- for (int i = 0; i < 5; i++) {
- backgroundIcon[i] = nullptr;
+GRSurface* ScreenRecoveryUI::GetCurrentFrame() {
+ if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
+ return intro_done ? loopFrames[current_frame] : introFrames[current_frame];
}
- pthread_mutex_init(&updateMutex, nullptr);
+ return error_icon;
}
-// Clear the screen and draw the currently selected background icon (if any).
-// Should only be called with updateMutex locked.
-void ScreenRecoveryUI::draw_background_locked(Icon icon) {
- pagesIdentical = false;
- gr_color(0, 0, 0, 255);
- gr_clear();
+GRSurface* ScreenRecoveryUI::GetCurrentText() {
+ switch (currentIcon) {
+ case ERASING: return erasing_text;
+ case ERROR: return error_text;
+ case INSTALLING_UPDATE: return installing_text;
+ case NO_COMMAND: return no_command_text;
+ case NONE: abort();
+ }
+}
- if (icon) {
- GRSurface* surface = backgroundIcon[icon];
- if (icon == INSTALLING_UPDATE || icon == ERASING) {
- surface = installation[installingFrame];
- }
- GRSurface* text_surface = backgroundText[icon];
+int ScreenRecoveryUI::PixelsFromDp(int dp) {
+ return dp * density_;
+}
+
+// Here's the intended layout:
+
+// | regular large
+// ---------+--------------------
+// | 220dp 366dp
+// icon | (200dp) (200dp)
+// | 68dp 68dp
+// text | (14sp) (14sp)
+// | 32dp 32dp
+// progress | (2dp) (2dp)
+// | 194dp 340dp
- int iconWidth = gr_get_width(surface);
- int iconHeight = gr_get_height(surface);
- int textWidth = gr_get_width(text_surface);
- int textHeight = gr_get_height(text_surface);
- int stageHeight = gr_get_height(stageMarkerEmpty);
+// Note that "baseline" is actually the *top* of each icon (because that's how our drawing
+// routines work), so that's the more useful measurement for calling code.
- int sh = (max_stage >= 0) ? stageHeight : 0;
+int ScreenRecoveryUI::GetAnimationBaseline() {
+ return GetTextBaseline() - PixelsFromDp(68) - gr_get_height(loopFrames[0]);
+}
- iconX = (gr_fb_width() - iconWidth) / 2;
- iconY = (gr_fb_height() - (iconHeight+textHeight+40+sh)) / 2;
+int ScreenRecoveryUI::GetTextBaseline() {
+ return GetProgressBaseline() - PixelsFromDp(32) - gr_get_height(installing_text);
+}
- int textX = (gr_fb_width() - textWidth) / 2;
- int textY = ((gr_fb_height() - (iconHeight+textHeight+40+sh)) / 2) + iconHeight + 40;
+int ScreenRecoveryUI::GetProgressBaseline() {
+ return gr_fb_height() - PixelsFromDp(is_large_ ? 340 : 194) - gr_get_height(progressBarFill);
+}
- gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
- if (stageHeight > 0) {
- int sw = gr_get_width(stageMarkerEmpty);
+// Clear the screen and draw the currently selected background icon (if any).
+// Should only be called with updateMutex locked.
+void ScreenRecoveryUI::draw_background_locked() {
+ pagesIdentical = false;
+ gr_color(0, 0, 0, 255);
+ gr_clear();
+
+ if (currentIcon != NONE) {
+ if (max_stage != -1) {
+ int stage_height = gr_get_height(stageMarkerEmpty);
+ int stage_width = gr_get_width(stageMarkerEmpty);
int x = (gr_fb_width() - max_stage * gr_get_width(stageMarkerEmpty)) / 2;
- int y = iconY + iconHeight + 20;
+ int y = gr_fb_height() - stage_height;
for (int i = 0; i < max_stage; ++i) {
- gr_blit((i < stage) ? stageMarkerFill : stageMarkerEmpty,
- 0, 0, sw, stageHeight, x, y);
- x += sw;
+ GRSurface* stage_surface = (i < stage) ? stageMarkerFill : stageMarkerEmpty;
+ gr_blit(stage_surface, 0, 0, stage_width, stage_height, x, y);
+ x += stage_width;
}
}
+ GRSurface* text_surface = GetCurrentText();
+ int text_x = (gr_fb_width() - gr_get_width(text_surface)) / 2;
+ int text_y = GetTextBaseline();
gr_color(255, 255, 255, 255);
- gr_texticon(textX, textY, text_surface);
+ gr_texticon(text_x, text_y, text_surface);
}
}
-// Draw the progress bar (if any) on the screen. Does not flip pages.
+// Draws the animation and progress bar (if any) on the screen.
+// Does not flip pages.
// Should only be called with updateMutex locked.
-void ScreenRecoveryUI::draw_progress_locked() {
- if (currentIcon == ERROR) return;
-
- if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
- GRSurface* icon = installation[installingFrame];
- gr_blit(icon, 0, 0, gr_get_width(icon), gr_get_height(icon), iconX, iconY);
+void ScreenRecoveryUI::draw_foreground_locked() {
+ if (currentIcon != NONE) {
+ GRSurface* frame = GetCurrentFrame();
+ int frame_width = gr_get_width(frame);
+ int frame_height = gr_get_height(frame);
+ int frame_x = (gr_fb_width() - frame_width) / 2;
+ int frame_y = GetAnimationBaseline();
+ gr_blit(frame, 0, 0, frame_width, frame_height, frame_x, frame_y);
}
if (progressBarType != EMPTY) {
- int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);
int width = gr_get_width(progressBarEmpty);
int height = gr_get_height(progressBarEmpty);
- int dx = (gr_fb_width() - width)/2;
- int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
+ int progress_x = (gr_fb_width() - width)/2;
+ int progress_y = GetProgressBaseline();
// Erase behind the progress bar (in case this was a progress-only update)
gr_color(0, 0, 0, 255);
- gr_fill(dx, dy, width, height);
+ gr_fill(progress_x, progress_y, width, height);
if (progressBarType == DETERMINATE) {
float p = progressScopeStart + progress * progressScopeSize;
@@ -158,18 +189,20 @@ void ScreenRecoveryUI::draw_progress_locked() {
if (rtl_locale) {
// Fill the progress bar from right to left.
if (pos > 0) {
- gr_blit(progressBarFill, width-pos, 0, pos, height, dx+width-pos, dy);
+ gr_blit(progressBarFill, width-pos, 0, pos, height,
+ progress_x+width-pos, progress_y);
}
if (pos < width-1) {
- gr_blit(progressBarEmpty, 0, 0, width-pos, height, dx, dy);
+ gr_blit(progressBarEmpty, 0, 0, width-pos, height, progress_x, progress_y);
}
} else {
// Fill the progress bar from left to right.
if (pos > 0) {
- gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);
+ gr_blit(progressBarFill, 0, 0, pos, height, progress_x, progress_y);
}
if (pos < width-1) {
- gr_blit(progressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
+ gr_blit(progressBarEmpty, pos, 0, width-pos, height,
+ progress_x+pos, progress_y);
}
}
}
@@ -213,14 +246,14 @@ void ScreenRecoveryUI::DrawHorizontalRule(int* y) {
*y += 4;
}
-void ScreenRecoveryUI::DrawTextLine(int* y, const char* line, bool bold) {
- gr_text(4, *y, line, bold);
- *y += char_height + 4;
+void ScreenRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) {
+ gr_text(x, *y, line, bold);
+ *y += char_height_ + 4;
}
-void ScreenRecoveryUI::DrawTextLines(int* y, const char* const* lines) {
+void ScreenRecoveryUI::DrawTextLines(int x, int* y, const char* const* lines) {
for (size_t i = 0; lines != nullptr && lines[i] != nullptr; ++i) {
- DrawTextLine(y, lines[i], false);
+ DrawTextLine(x, y, lines[i], false);
}
}
@@ -239,8 +272,8 @@ static const char* LONG_PRESS_HELP[] = {
// Should only be called with updateMutex locked.
void ScreenRecoveryUI::draw_screen_locked() {
if (!show_text) {
- draw_background_locked(currentIcon);
- draw_progress_locked();
+ draw_background_locked();
+ draw_foreground_locked();
} else {
gr_color(0, 0, 0, 255);
gr_clear();
@@ -251,14 +284,14 @@ void ScreenRecoveryUI::draw_screen_locked() {
property_get("ro.bootimage.build.fingerprint", recovery_fingerprint, "");
SetColor(INFO);
- DrawTextLine(&y, "Android Recovery", true);
+ DrawTextLine(TEXT_INDENT, &y, "Android Recovery", true);
for (auto& chunk : android::base::Split(recovery_fingerprint, ":")) {
- DrawTextLine(&y, chunk.c_str(), false);
+ DrawTextLine(TEXT_INDENT, &y, chunk.c_str(), false);
}
- DrawTextLines(&y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP);
+ DrawTextLines(TEXT_INDENT, &y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP);
SetColor(HEADER);
- DrawTextLines(&y, menu_headers_);
+ DrawTextLines(TEXT_INDENT, &y, menu_headers_);
SetColor(MENU);
DrawHorizontalRule(&y);
@@ -267,7 +300,7 @@ void ScreenRecoveryUI::draw_screen_locked() {
if (i == menu_sel) {
// Draw the highlight bar.
SetColor(IsLongPress() ? MENU_SEL_BG_ACTIVE : MENU_SEL_BG);
- gr_fill(0, y - 2, gr_fb_width(), y + char_height + 2);
+ gr_fill(0, y - 2, gr_fb_width(), y + char_height_ + 2);
// Bold white text for the selected item.
SetColor(MENU_SEL_FG);
gr_text(4, y, menu_[i], true);
@@ -275,7 +308,7 @@ void ScreenRecoveryUI::draw_screen_locked() {
} else {
gr_text(4, y, menu_[i], false);
}
- y += char_height + 4;
+ y += char_height_ + 4;
}
DrawHorizontalRule(&y);
}
@@ -286,9 +319,9 @@ void ScreenRecoveryUI::draw_screen_locked() {
SetColor(LOG);
int row = (text_top_ + text_rows_ - 1) % text_rows_;
size_t count = 0;
- for (int ty = gr_fb_height() - char_height;
+ for (int ty = gr_fb_height() - char_height_;
ty >= y && count < text_rows_;
- ty -= char_height, ++count) {
+ ty -= char_height_, ++count) {
gr_text(0, ty, text_[row], false);
--row;
if (row < 0) row = text_rows_ - 1;
@@ -310,7 +343,7 @@ void ScreenRecoveryUI::update_progress_locked() {
draw_screen_locked(); // Must redraw the whole screen
pagesIdentical = true;
} else {
- draw_progress_locked(); // Draw only the progress bar and overlays
+ draw_foreground_locked(); // Draw only the progress bar and overlays
}
gr_flip();
}
@@ -327,14 +360,23 @@ void ScreenRecoveryUI::ProgressThreadLoop() {
double start = now();
pthread_mutex_lock(&updateMutex);
- int redraw = 0;
+ bool redraw = false;
// update the installation animation, if active
// skip this if we have a text overlay (too expensive to update)
- if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) &&
- installing_frames > 0 && !show_text) {
- installingFrame = (installingFrame + 1) % installing_frames;
- redraw = 1;
+ if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) && !show_text) {
+ if (!intro_done) {
+ if (current_frame == intro_frames - 1) {
+ intro_done = true;
+ current_frame = 0;
+ } else {
+ ++current_frame;
+ }
+ } else {
+ current_frame = (current_frame + 1) % loop_frames;
+ }
+
+ redraw = true;
}
// move the progress bar forward on timed intervals, if configured
@@ -345,7 +387,7 @@ void ScreenRecoveryUI::ProgressThreadLoop() {
if (p > 1.0) p = 1.0;
if (p > progress) {
progress = p;
- redraw = 1;
+ redraw = true;
}
}
@@ -363,22 +405,14 @@ void ScreenRecoveryUI::ProgressThreadLoop() {
void ScreenRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) {
int result = res_create_display_surface(filename, surface);
if (result < 0) {
- LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
- }
-}
-
-void ScreenRecoveryUI::LoadBitmapArray(const char* filename, int* frames, int* fps,
- GRSurface*** surface) {
- int result = res_create_multi_display_surface(filename, frames, fps, surface);
- if (result < 0) {
- LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
+ LOGE("couldn't load bitmap %s (error %d)\n", filename, result);
}
}
void ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, GRSurface** surface) {
int result = res_create_localized_alpha_surface(filename, locale, surface);
if (result < 0) {
- LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
+ LOGE("couldn't load bitmap %s (error %d)\n", filename, result);
}
}
@@ -391,12 +425,25 @@ static char** Alloc2d(size_t rows, size_t cols) {
return result;
}
+// Choose the right background string to display during update.
+void ScreenRecoveryUI::SetSystemUpdateText(bool security_update) {
+ if (security_update) {
+ LoadLocalizedBitmap("installing_security_text", &installing_text);
+ } else {
+ LoadLocalizedBitmap("installing_text", &installing_text);
+ }
+ Redraw();
+}
+
void ScreenRecoveryUI::Init() {
gr_init();
- gr_font_size(&char_width, &char_height);
- text_rows_ = gr_fb_height() / char_height;
- text_cols_ = gr_fb_width() / char_width;
+ density_ = static_cast<float>(property_get_int32("ro.sf.lcd_density", 160)) / 160.f;
+ is_large_ = gr_fb_height() > PixelsFromDp(800);
+
+ gr_font_size(&char_width_, &char_height_);
+ text_rows_ = gr_fb_height() / char_height_;
+ text_cols_ = gr_fb_width() / char_width_;
text_ = Alloc2d(text_rows_, text_cols_ + 1);
file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1);
@@ -405,31 +452,64 @@ void ScreenRecoveryUI::Init() {
text_col_ = text_row_ = 0;
text_top_ = 1;
- backgroundIcon[NONE] = nullptr;
- LoadBitmapArray("icon_installing", &installing_frames, &animation_fps, &installation);
- backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[0] : nullptr;
- backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
- LoadBitmap("icon_error", &backgroundIcon[ERROR]);
- backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
+ LoadBitmap("icon_error", &error_icon);
LoadBitmap("progress_empty", &progressBarEmpty);
LoadBitmap("progress_fill", &progressBarFill);
+
LoadBitmap("stage_empty", &stageMarkerEmpty);
LoadBitmap("stage_fill", &stageMarkerFill);
- LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
- LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
- LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
- LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
+ // Background text for "installing_update" could be "installing update"
+ // or "installing security update". It will be set after UI init according
+ // to commands in BCB.
+ installing_text = nullptr;
+ LoadLocalizedBitmap("erasing_text", &erasing_text);
+ LoadLocalizedBitmap("no_command_text", &no_command_text);
+ LoadLocalizedBitmap("error_text", &error_text);
+
+ LoadAnimation();
pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this);
RecoveryUI::Init();
}
+void ScreenRecoveryUI::LoadAnimation() {
+ // How many frames of intro and loop do we have?
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/res/images"), closedir);
+ dirent* de;
+ while ((de = readdir(dir.get())) != nullptr) {
+ int value;
+ if (sscanf(de->d_name, "intro%d", &value) == 1 && intro_frames < (value + 1)) {
+ intro_frames = value + 1;
+ } else if (sscanf(de->d_name, "loop%d", &value) == 1 && loop_frames < (value + 1)) {
+ loop_frames = value + 1;
+ }
+ }
+
+ // It's okay to not have an intro.
+ if (intro_frames == 0) intro_done = true;
+ // But you must have an animation.
+ if (loop_frames == 0) abort();
+
+ introFrames = new GRSurface*[intro_frames];
+ for (int i = 0; i < intro_frames; ++i) {
+ // TODO: remember the names above, so we don't have to hard-code the number of 0s.
+ LoadBitmap(android::base::StringPrintf("intro%05d", i).c_str(), &introFrames[i]);
+ }
+
+ loopFrames = new GRSurface*[loop_frames];
+ for (int i = 0; i < loop_frames; ++i) {
+ LoadBitmap(android::base::StringPrintf("loop%05d", i).c_str(), &loopFrames[i]);
+ }
+}
+
void ScreenRecoveryUI::SetLocale(const char* new_locale) {
- if (new_locale) {
- this->locale = new_locale;
+ this->locale = new_locale;
+ this->rtl_locale = false;
+
+ if (locale) {
char* lang = strdup(locale);
for (char* p = lang; *p; ++p) {
if (*p == '_') {
@@ -438,8 +518,7 @@ void ScreenRecoveryUI::SetLocale(const char* new_locale) {
}
}
- // A bit cheesy: keep an explicit list of supported languages
- // that are RTL.
+ // A bit cheesy: keep an explicit list of supported RTL languages.
if (strcmp(lang, "ar") == 0 || // Arabic
strcmp(lang, "fa") == 0 || // Persian (Farsi)
strcmp(lang, "he") == 0 || // Hebrew (new language code)
@@ -448,8 +527,6 @@ void ScreenRecoveryUI::SetLocale(const char* new_locale) {
rtl_locale = true;
}
free(lang);
- } else {
- new_locale = nullptr;
}
}
diff --git a/screen_ui.h b/screen_ui.h
index 08a5f44a9..4319b76ce 100644
--- a/screen_ui.h
+++ b/screen_ui.h
@@ -34,6 +34,7 @@ class ScreenRecoveryUI : public RecoveryUI {
// overall recovery state ("background image")
void SetBackground(Icon icon);
+ void SetSystemUpdateText(bool security_update);
// progress indicator
void SetProgressType(ProgressType type);
@@ -67,16 +68,28 @@ class ScreenRecoveryUI : public RecoveryUI {
};
void SetColor(UIElement e);
- private:
+ protected:
Icon currentIcon;
- int installingFrame;
+
const char* locale;
- bool rtl_locale;
+ bool intro_done;
+ int current_frame;
+
+ // The scale factor from dp to pixels. 1.0 for mdpi, 4.0 for xxxhdpi.
+ float density_;
+ // True if we should use the large layout.
+ bool is_large_;
+
+ GRSurface* error_icon;
+
+ GRSurface* erasing_text;
+ GRSurface* error_text;
+ GRSurface* installing_text;
+ GRSurface* no_command_text;
+
+ GRSurface** introFrames;
+ GRSurface** loopFrames;
- pthread_mutex_t updateMutex;
- GRSurface* backgroundIcon[5];
- GRSurface* backgroundText[5];
- GRSurface** installation;
GRSurface* progressBarEmpty;
GRSurface* progressBarFill;
GRSurface* stageMarkerEmpty;
@@ -109,21 +122,29 @@ class ScreenRecoveryUI : public RecoveryUI {
pthread_t progress_thread_;
- // The following two are parsed from the image file
- // (e.g. '/res/images/icon_installing.png').
- int animation_fps;
- int installing_frames;
+ // Number of intro frames and loop frames in the animation.
+ int intro_frames;
+ int loop_frames;
- int iconX, iconY;
+ // Number of frames per sec (default: 30) for both parts of the animation.
+ int animation_fps;
int stage, max_stage;
- void draw_background_locked(Icon icon);
- void draw_progress_locked();
+ int char_width_;
+ int char_height_;
+ pthread_mutex_t updateMutex;
+ bool rtl_locale;
+
+ void draw_background_locked();
+ void draw_foreground_locked();
void draw_screen_locked();
void update_screen_locked();
void update_progress_locked();
+ GRSurface* GetCurrentFrame();
+ GRSurface* GetCurrentText();
+
static void* ProgressThreadStartRoutine(void* data);
void ProgressThreadLoop();
@@ -132,13 +153,18 @@ class ScreenRecoveryUI : public RecoveryUI {
void PutChar(char);
void ClearText();
- void DrawHorizontalRule(int* y);
- void DrawTextLine(int* y, const char* line, bool bold);
- void DrawTextLines(int* y, const char* const* lines);
-
+ void LoadAnimation();
void LoadBitmap(const char* filename, GRSurface** surface);
- void LoadBitmapArray(const char* filename, int* frames, int* fps, GRSurface*** surface);
void LoadLocalizedBitmap(const char* filename, GRSurface** surface);
+
+ int PixelsFromDp(int dp);
+ int GetAnimationBaseline();
+ int GetProgressBaseline();
+ int GetTextBaseline();
+
+ void DrawHorizontalRule(int* y);
+ void DrawTextLine(int x, int* y, const char* line, bool bold);
+ void DrawTextLines(int x, int* y, const char* const* lines);
};
#endif // RECOVERY_UI_H
diff --git a/tests/Android.mk b/tests/Android.mk
index 7b004b2a0..4509c420f 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -21,9 +21,13 @@ include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_MODULE := recovery_unit_test
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_STATIC_LIBRARIES := libverifier
+LOCAL_STATIC_LIBRARIES := \
+ libverifier \
+ libminui
+
LOCAL_SRC_FILES := unit/asn1_decoder_test.cpp
LOCAL_SRC_FILES += unit/recovery_test.cpp
+LOCAL_SRC_FILES += unit/locale_test.cpp
LOCAL_C_INCLUDES := bootable/recovery
LOCAL_SHARED_LIBRARIES := liblog
include $(BUILD_NATIVE_TEST)
@@ -31,12 +35,18 @@ include $(BUILD_NATIVE_TEST)
# Component tests
include $(CLEAR_VARS)
LOCAL_CLANG := true
+LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MODULE := recovery_component_test
LOCAL_C_INCLUDES := bootable/recovery
-LOCAL_SRC_FILES := component/verifier_test.cpp
+LOCAL_SRC_FILES := \
+ component/verifier_test.cpp \
+ component/applypatch_test.cpp
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_STATIC_LIBRARIES := \
+ libapplypatch \
+ libotafault \
+ libmtdutils \
libbase \
libverifier \
libcrypto_utils_static \
@@ -44,6 +54,8 @@ LOCAL_STATIC_LIBRARIES := \
libminui \
libminzip \
libcutils \
+ libbz \
+ libz \
libc
testdata_out_path := $(TARGET_OUT_DATA_NATIVE_TESTS)/recovery
diff --git a/tests/common/test_constants.h b/tests/common/test_constants.h
new file mode 100644
index 000000000..3490f6805
--- /dev/null
+++ b/tests/common/test_constants.h
@@ -0,0 +1,25 @@
+/*
+ * 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 agree to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _OTA_TEST_CONSTANTS_H
+#define _OTA_TEST_CONSTANTS_H
+
+#if defined(__LP64__)
+#define NATIVE_TEST_PATH "/nativetest64"
+#else
+#define NATIVE_TEST_PATH "/nativetest"
+#endif
+
+#endif
diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp
new file mode 100644
index 000000000..b44ddd17c
--- /dev/null
+++ b/tests/component/applypatch_test.cpp
@@ -0,0 +1,392 @@
+/*
+ * 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 agree to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/test_utils.h>
+
+#include "applypatch/applypatch.h"
+#include "common/test_constants.h"
+#include "openssl/sha.h"
+#include "print_sha1.h"
+
+static const std::string DATA_PATH = getenv("ANDROID_DATA");
+static const std::string TESTDATA_PATH = "/recovery/testdata";
+static const std::string WORK_FS = "/data";
+
+static std::string sha1sum(const std::string& fname) {
+ uint8_t digest[SHA_DIGEST_LENGTH];
+ std::string data;
+ android::base::ReadFileToString(fname, &data);
+
+ SHA1((const uint8_t*)data.c_str(), data.size(), digest);
+ return print_sha1(digest);
+}
+
+static void mangle_file(const std::string& fname) {
+ FILE* fh = fopen(&fname[0], "w");
+ int r;
+ for (int i=0; i < 1024; i++) {
+ r = rand();
+ fwrite(&r, sizeof(short), 1, fh);
+ }
+ fclose(fh);
+}
+
+static bool file_cmp(std::string& f1, std::string& f2) {
+ std::string c1;
+ std::string c2;
+ android::base::ReadFileToString(f1, &c1);
+ android::base::ReadFileToString(f2, &c2);
+ return c1 == c2;
+}
+
+static std::string from_testdata_base(const std::string fname) {
+ return android::base::StringPrintf("%s%s%s/%s",
+ &DATA_PATH[0],
+ &NATIVE_TEST_PATH[0],
+ &TESTDATA_PATH[0],
+ &fname[0]);
+}
+
+class ApplyPatchTest : public ::testing::Test {
+ public:
+ static void SetUpTestCase() {
+ // set up files
+ old_file = from_testdata_base("old.file");
+ new_file = from_testdata_base("new.file");
+ patch_file = from_testdata_base("patch.bsdiff");
+ rand_file = "/cache/applypatch_test_rand.file";
+ cache_file = "/cache/saved.file";
+
+ // write stuff to rand_file
+ android::base::WriteStringToFile("hello", rand_file);
+
+ // set up SHA constants
+ old_sha1 = sha1sum(old_file);
+ new_sha1 = sha1sum(new_file);
+ srand(time(NULL));
+ bad_sha1_a = android::base::StringPrintf("%040x", rand());
+ bad_sha1_b = android::base::StringPrintf("%040x", rand());
+
+ struct stat st;
+ stat(&new_file[0], &st);
+ new_size = st.st_size;
+ }
+
+ static std::string old_file;
+ static std::string new_file;
+ static std::string rand_file;
+ static std::string cache_file;
+ static std::string patch_file;
+
+ static std::string old_sha1;
+ static std::string new_sha1;
+ static std::string bad_sha1_a;
+ static std::string bad_sha1_b;
+
+ static size_t new_size;
+};
+
+std::string ApplyPatchTest::old_file;
+std::string ApplyPatchTest::new_file;
+
+static void cp(std::string src, std::string tgt) {
+ std::string cmd = android::base::StringPrintf("cp %s %s",
+ &src[0],
+ &tgt[0]);
+ system(&cmd[0]);
+}
+
+static void backup_old() {
+ cp(ApplyPatchTest::old_file, ApplyPatchTest::cache_file);
+}
+
+static void restore_old() {
+ cp(ApplyPatchTest::cache_file, ApplyPatchTest::old_file);
+}
+
+class ApplyPatchCacheTest : public ApplyPatchTest {
+ public:
+ virtual void SetUp() {
+ backup_old();
+ }
+
+ virtual void TearDown() {
+ restore_old();
+ }
+};
+
+class ApplyPatchFullTest : public ApplyPatchCacheTest {
+ public:
+ static void SetUpTestCase() {
+ ApplyPatchTest::SetUpTestCase();
+ unsigned long free_kb = FreeSpaceForFile(&WORK_FS[0]);
+ ASSERT_GE(free_kb * 1024, new_size * 3 / 2);
+ output_f = new TemporaryFile();
+ output_loc = std::string(output_f->path);
+
+ struct FileContents fc;
+
+ ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc));
+ Value* patch1 = new Value();
+ patch1->type = VAL_BLOB;
+ patch1->size = fc.data.size();
+ patch1->data = static_cast<char*>(malloc(fc.data.size()));
+ memcpy(patch1->data, fc.data.data(), fc.data.size());
+ patches.push_back(patch1);
+
+ ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc));
+ Value* patch2 = new Value();
+ patch2->type = VAL_BLOB;
+ patch2->size = fc.st.st_size;
+ patch2->data = static_cast<char*>(malloc(fc.data.size()));
+ memcpy(patch2->data, fc.data.data(), fc.data.size());
+ patches.push_back(patch2);
+ }
+ static void TearDownTestCase() {
+ delete output_f;
+ for (auto it = patches.begin(); it != patches.end(); ++it) {
+ free((*it)->data);
+ delete *it;
+ }
+ patches.clear();
+ }
+
+ static std::vector<Value*> patches;
+ static TemporaryFile* output_f;
+ static std::string output_loc;
+};
+
+class ApplyPatchDoubleCacheTest : public ApplyPatchFullTest {
+ public:
+ virtual void SetUp() {
+ ApplyPatchCacheTest::SetUp();
+ cp(cache_file, "/cache/reallysaved.file");
+ }
+
+ virtual void TearDown() {
+ cp("/cache/reallysaved.file", cache_file);
+ ApplyPatchCacheTest::TearDown();
+ }
+};
+
+std::string ApplyPatchTest::rand_file;
+std::string ApplyPatchTest::patch_file;
+std::string ApplyPatchTest::cache_file;
+std::string ApplyPatchTest::old_sha1;
+std::string ApplyPatchTest::new_sha1;
+std::string ApplyPatchTest::bad_sha1_a;
+std::string ApplyPatchTest::bad_sha1_b;
+
+size_t ApplyPatchTest::new_size;
+
+std::vector<Value*> ApplyPatchFullTest::patches;
+TemporaryFile* ApplyPatchFullTest::output_f;
+std::string ApplyPatchFullTest::output_loc;
+
+TEST_F(ApplyPatchTest, CheckModeSingle) {
+ char* s = &old_sha1[0];
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s));
+}
+
+TEST_F(ApplyPatchTest, CheckModeMultiple) {
+ char* argv[3] = {
+ &bad_sha1_a[0],
+ &old_sha1[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv));
+}
+
+TEST_F(ApplyPatchTest, CheckModeFailure) {
+ char* argv[2] = {
+ &bad_sha1_a[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) {
+ mangle_file(old_file);
+ char* s = &old_sha1[0];
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) {
+ mangle_file(old_file);
+ char* argv[3] = {
+ &bad_sha1_a[0],
+ &old_sha1[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) {
+ mangle_file(old_file);
+ char* argv[2] = {
+ &bad_sha1_a[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) {
+ unlink(&old_file[0]);
+ char* s = &old_sha1[0];
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) {
+ unlink(&old_file[0]);
+ char* argv[3] = {
+ &bad_sha1_a[0],
+ &old_sha1[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv));
+}
+
+TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) {
+ unlink(&old_file[0]);
+ char* argv[2] = {
+ &bad_sha1_a[0],
+ &bad_sha1_b[0]
+ };
+ ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv));
+}
+
+TEST_F(ApplyPatchFullTest, ApplyInPlace) {
+ std::vector<char*> sha1s;
+ sha1s.push_back(&bad_sha1_a[0]);
+ sha1s.push_back(&old_sha1[0]);
+
+ int ap_result = applypatch(&old_file[0],
+ "-",
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(old_file, new_file));
+ // reapply, applypatch is idempotent so it should succeed
+ ap_result = applypatch(&old_file[0],
+ "-",
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(old_file, new_file));
+}
+
+TEST_F(ApplyPatchFullTest, ApplyInNewLocation) {
+ std::vector<char*> sha1s;
+ sha1s.push_back(&bad_sha1_a[0]);
+ sha1s.push_back(&old_sha1[0]);
+ int ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(output_loc, new_file));
+ ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(output_loc, new_file));
+}
+
+TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) {
+ mangle_file(old_file);
+ std::vector<char*> sha1s;
+ sha1s.push_back(&bad_sha1_a[0]);
+ sha1s.push_back(&old_sha1[0]);
+ int ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(output_loc, new_file));
+ ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_EQ(0, ap_result);
+ ASSERT_TRUE(file_cmp(output_loc, new_file));
+}
+
+TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) {
+ mangle_file(old_file);
+ mangle_file(cache_file);
+
+ std::vector<char*> sha1s;
+ sha1s.push_back(&bad_sha1_a[0]);
+ sha1s.push_back(&old_sha1[0]);
+ int ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_NE(0, ap_result);
+ ASSERT_FALSE(file_cmp(output_loc, new_file));
+ ap_result = applypatch(&old_file[0],
+ &output_loc[0],
+ &new_sha1[0],
+ new_size,
+ 2,
+ sha1s.data(),
+ patches.data(),
+ nullptr);
+ ASSERT_NE(0, ap_result);
+ ASSERT_FALSE(file_cmp(output_loc, new_file));
+}
diff --git a/tests/component/verifier_test.cpp b/tests/component/verifier_test.cpp
index b5d70327e..d7166dfaf 100644
--- a/tests/component/verifier_test.cpp
+++ b/tests/component/verifier_test.cpp
@@ -31,16 +31,11 @@
#include <android-base/stringprintf.h>
#include "common.h"
+#include "common/test_constants.h"
#include "minzip/SysUtil.h"
#include "ui.h"
#include "verifier.h"
-#if defined(__LP64__)
-#define NATIVE_TEST_PATH "/nativetest64"
-#else
-#define NATIVE_TEST_PATH "/nativetest"
-#endif
-
static const char* DATA_PATH = getenv("ANDROID_DATA");
static const char* TESTDATA_PATH = "/recovery/testdata/";
@@ -51,6 +46,7 @@ class MockUI : public RecoveryUI {
void SetStage(int, int) { }
void SetLocale(const char*) { }
void SetBackground(Icon /*icon*/) { }
+ void SetSystemUpdateText(bool /*security_update*/) { }
void SetProgressType(ProgressType /*determinate*/) { }
void ShowProgress(float /*portion*/, float /*seconds*/) { }
diff --git a/tests/testdata/new.file b/tests/testdata/new.file
new file mode 100644
index 000000000..cdeb8fd50
--- /dev/null
+++ b/tests/testdata/new.file
Binary files differ
diff --git a/tests/testdata/old.file b/tests/testdata/old.file
new file mode 100644
index 000000000..166c8732e
--- /dev/null
+++ b/tests/testdata/old.file
Binary files differ
diff --git a/tests/testdata/patch.bsdiff b/tests/testdata/patch.bsdiff
new file mode 100644
index 000000000..b78d38573
--- /dev/null
+++ b/tests/testdata/patch.bsdiff
Binary files differ
diff --git a/tests/unit/locale_test.cpp b/tests/unit/locale_test.cpp
new file mode 100644
index 000000000..0e515f8c1
--- /dev/null
+++ b/tests/unit/locale_test.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "minui/minui.h"
+
+TEST(LocaleTest, Misc) {
+ EXPECT_TRUE(matches_locale("zh_CN", "zh_CN_#Hans"));
+ EXPECT_TRUE(matches_locale("zh", "zh_CN_#Hans"));
+ EXPECT_FALSE(matches_locale("zh_HK", "zh_CN_#Hans"));
+ EXPECT_TRUE(matches_locale("en_GB", "en_GB"));
+ EXPECT_TRUE(matches_locale("en", "en_GB"));
+ EXPECT_FALSE(matches_locale("en_GB", "en"));
+ EXPECT_FALSE(matches_locale("en_GB", "en_US"));
+}
diff --git a/tools/recovery_l10n/res/layout/main.xml b/tools/recovery_l10n/res/layout/main.xml
index 0900b1102..05a16e1e4 100644
--- a/tools/recovery_l10n/res/layout/main.xml
+++ b/tools/recovery_l10n/res/layout/main.xml
@@ -19,7 +19,9 @@
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="#ffffffff"
+ android:fontFamily="sans-serif-medium"
+ android:textColor="#fff5f5f5"
+ android:textSize="14sp"
android:background="#ff000000"
android:maxWidth="480px"
android:gravity="center"
diff --git a/tools/recovery_l10n/res/values/strings.xml b/tools/recovery_l10n/res/values/strings.xml
index f6193ab17..971e038d3 100644
--- a/tools/recovery_l10n/res/values/strings.xml
+++ b/tools/recovery_l10n/res/values/strings.xml
@@ -13,18 +13,18 @@
<!-- Displayed on the screen beneath the animated android while the
system is installing an update. [CHAR LIMIT=60] -->
- <string name="recovery_installing">Installing system update\u2026</string>
+ <string name="recovery_installing">Installing system update</string>
<!-- Displayed on the screen beneath the animated android while the
system is erasing a partition (either a data wipe aka "factory
reset", or a cache wipe). [CHAR LIMIT=60] -->
- <string name="recovery_erasing">Erasing\u2026</string>
+ <string name="recovery_erasing">Erasing</string>
<!-- Displayed on the screen when the user has gotten into recovery
mode without a command to run. Will not normally happen, but
users (especially developers) may boot into recovery mode
manually via special key combinations. [CHAR LIMIT=60] -->
- <string name="recovery_no_command">No command.</string>
+ <string name="recovery_no_command">No command</string>
<!-- Displayed on the triangle-! screen when a system update
installation or data wipe procedure encounters an error. [CHAR
@@ -33,6 +33,6 @@
<!-- Displayed on the screen beneath the animation while the
system is installing a security update. [CHAR LIMIT=60] -->
- <string name="recovery_installing_security">Installing security update\u2026</string>
+ <string name="recovery_installing_security">Installing security update</string>
</resources>
diff --git a/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java b/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
index 3f2bebe60..817a3ad7d 100644
--- a/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
+++ b/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
@@ -149,12 +149,9 @@ public class Main extends Activity {
String[] localeNames = getAssets().getLocales();
Arrays.sort(localeNames);
ArrayList<Locale> locales = new ArrayList<Locale>();
- for (String ln : localeNames) {
- int u = ln.indexOf('_');
- if (u >= 0) {
- Log.i(TAG, "locale = " + ln);
- locales.add(new Locale(ln.substring(0, u), ln.substring(u+1)));
- }
+ for (String localeName : localeNames) {
+ Log.i(TAG, "locale = " + localeName);
+ locales.add(Locale.forLanguageTag(localeName));
}
final Runnable seq = buildSequence(locales.toArray(new Locale[0]));
diff --git a/ui.h b/ui.h
index ca72911db..82d95a346 100644
--- a/ui.h
+++ b/ui.h
@@ -39,6 +39,7 @@ class RecoveryUI {
// Set the overall recovery state ("background image").
enum Icon { NONE, INSTALLING_UPDATE, ERASING, NO_COMMAND, ERROR };
virtual void SetBackground(Icon icon) = 0;
+ virtual void SetSystemUpdateText(bool security_update) = 0;
// --- progress indicator ---
enum ProgressType { EMPTY, INDETERMINATE, DETERMINATE };
diff --git a/uncrypt/Android.mk b/uncrypt/Android.mk
index 6422cb2f4..09cfdfca5 100644
--- a/uncrypt/Android.mk
+++ b/uncrypt/Android.mk
@@ -15,6 +15,15 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := bootloader_message_writer.cpp
+LOCAL_MODULE := libbootloader_message_writer
+LOCAL_STATIC_LIBRARIES := libbase libfs_mgr
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
LOCAL_CLANG := true
@@ -24,7 +33,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
LOCAL_MODULE := uncrypt
-LOCAL_STATIC_LIBRARIES := libbase liblog libfs_mgr libcutils
+LOCAL_STATIC_LIBRARIES := libbootloader_message_writer libbase \
+ liblog libfs_mgr libcutils \
LOCAL_INIT_RC := uncrypt.rc
diff --git a/uncrypt/bootloader_message_writer.cpp b/uncrypt/bootloader_message_writer.cpp
new file mode 100644
index 000000000..3bb106aa0
--- /dev/null
+++ b/uncrypt/bootloader_message_writer.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/system_properties.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <fs_mgr.h>
+
+#include "bootloader.h"
+
+static struct fstab* read_fstab(std::string* err) {
+ // The fstab path is always "/fstab.${ro.hardware}".
+ std::string fstab_path = "/fstab.";
+ char value[PROP_VALUE_MAX];
+ if (__system_property_get("ro.hardware", value) == 0) {
+ *err = "failed to get ro.hardware";
+ return nullptr;
+ }
+ fstab_path += value;
+ struct fstab* fstab = fs_mgr_read_fstab(fstab_path.c_str());
+ if (fstab == nullptr) {
+ *err = "failed to read " + fstab_path;
+ }
+ return fstab;
+}
+
+static std::string get_misc_blk_device(std::string* err) {
+ struct fstab* fstab = read_fstab(err);
+ if (fstab == nullptr) {
+ return "";
+ }
+ fstab_rec* record = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
+ if (record == nullptr) {
+ *err = "failed to find /misc partition";
+ return "";
+ }
+ return record->blk_device;
+}
+
+static bool write_bootloader_message(const bootloader_message& boot, std::string* err) {
+ std::string misc_blk_device = get_misc_blk_device(err);
+ if (misc_blk_device.empty()) {
+ return false;
+ }
+ android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY | O_SYNC));
+ if (fd.get() == -1) {
+ *err = android::base::StringPrintf("failed to open %s: %s", misc_blk_device.c_str(),
+ strerror(errno));
+ return false;
+ }
+ if (!android::base::WriteFully(fd.get(), &boot, sizeof(boot))) {
+ *err = android::base::StringPrintf("failed to write %s: %s", misc_blk_device.c_str(),
+ strerror(errno));
+ return false;
+ }
+ // TODO: O_SYNC and fsync duplicates each other?
+ if (fsync(fd.get()) == -1) {
+ *err = android::base::StringPrintf("failed to fsync %s: %s", misc_blk_device.c_str(),
+ strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+bool clear_bootloader_message(std::string* err) {
+ bootloader_message boot = {};
+ return write_bootloader_message(boot, err);
+}
+
+bool write_bootloader_message(const std::vector<std::string>& options, std::string* err) {
+ bootloader_message boot = {};
+ strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
+ strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
+ for (const auto& s : options) {
+ strlcat(boot.recovery, s.c_str(), sizeof(boot.recovery));
+ if (s.back() != '\n') {
+ strlcat(boot.recovery, "\n", sizeof(boot.recovery));
+ }
+ }
+ return write_bootloader_message(boot, err);
+}
+
+extern "C" bool write_bootloader_message(const char* options) {
+ std::string err;
+ return write_bootloader_message({options}, &err);
+}
diff --git a/uncrypt/include/bootloader_message_writer.h b/uncrypt/include/bootloader_message_writer.h
new file mode 100644
index 000000000..e0ca3f44a
--- /dev/null
+++ b/uncrypt/include/bootloader_message_writer.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#ifndef BOOTLOADER_MESSAGE_WRITER_H
+#define BOOTLOADER_MESSAGE_WRITER_H
+
+#ifdef __cplusplus
+#include <string>
+#include <vector>
+
+bool clear_bootloader_message(std::string* err);
+
+bool write_bootloader_message(const std::vector<std::string>& options, std::string* err);
+
+#else
+#include <stdbool.h>
+
+// C Interface.
+bool write_bootloader_message(const char* options);
+#endif
+
+#endif // BOOTLOADER_MESSAGE_WRITER_H
diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp
index a1de6a182..5697712aa 100644
--- a/uncrypt/uncrypt.cpp
+++ b/uncrypt/uncrypt.cpp
@@ -39,6 +39,53 @@
// Recovery can take this block map file and retrieve the underlying
// file data to use as an update package.
+/**
+ * In addition to the uncrypt work, uncrypt also takes care of setting and
+ * clearing the bootloader control block (BCB) at /misc partition.
+ *
+ * uncrypt is triggered as init services on demand. It uses socket to
+ * communicate with its caller (i.e. system_server). The socket is managed by
+ * init (i.e. created prior to the service starts, and destroyed when uncrypt
+ * exits).
+ *
+ * Below is the uncrypt protocol.
+ *
+ * a. caller b. init c. uncrypt
+ * --------------- ------------ --------------
+ * a1. ctl.start:
+ * setup-bcb /
+ * clear-bcb /
+ * uncrypt
+ *
+ * b2. create socket at
+ * /dev/socket/uncrypt
+ *
+ * c3. listen and accept
+ *
+ * a4. send a 4-byte int
+ * (message length)
+ * c5. receive message length
+ * a6. send message
+ * c7. receive message
+ * c8. <do the work; may send
+ * the progress>
+ * a9. <may handle progress>
+ * c10. <upon finishing>
+ * send "100" or "-1"
+ *
+ * a11. receive status code
+ * a12. send a 4-byte int to
+ * ack the receive of the
+ * final status code
+ * c13. receive and exit
+ *
+ * b14. destroy the socket
+ *
+ * Note that a12 and c13 are necessary to ensure a11 happens before the socket
+ * gets destroyed in b14.
+ */
+
+#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -49,6 +96,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -62,23 +110,32 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
+#include <bootloader_message_writer.h>
#include <cutils/android_reboot.h>
#include <cutils/properties.h>
+#include <cutils/sockets.h>
#include <fs_mgr.h>
#define LOG_TAG "uncrypt"
#include <log/log.h>
-#include "bootloader.h"
-
#define WINDOW_SIZE 5
+// uncrypt provides three services: SETUP_BCB, CLEAR_BCB and UNCRYPT.
+//
+// SETUP_BCB and CLEAR_BCB services use socket communication and do not rely
+// on /cache partitions. They will handle requests to reboot into recovery
+// (for applying updates for non-A/B devices, or factory resets for all
+// devices).
+//
+// UNCRYPT service still needs files on /cache partition (UNCRYPT_PATH_FILE
+// and CACHE_BLOCK_MAP). It will be working (and needed) only for non-A/B
+// devices, on which /cache partitions always exist.
static const std::string CACHE_BLOCK_MAP = "/cache/recovery/block.map";
-static const std::string COMMAND_FILE = "/cache/recovery/command";
-static const std::string STATUS_FILE = "/cache/recovery/uncrypt_status";
static const std::string UNCRYPT_PATH_FILE = "/cache/recovery/uncrypt_file";
+static const std::string UNCRYPT_SOCKET = "uncrypt";
-static struct fstab* fstab = NULL;
+static struct fstab* fstab = nullptr;
static int write_at_offset(unsigned char* buffer, size_t size, int wfd, off64_t offset) {
if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) {
@@ -152,6 +209,11 @@ static const char* find_block_device(const char* path, bool* encryptable, bool*
return NULL;
}
+static bool write_status_to_socket(int status, int socket) {
+ int status_out = htonl(status);
+ return android::base::WriteFully(socket, &status_out, sizeof(int));
+}
+
// Parse uncrypt_file to find the update package name.
static bool find_uncrypt_package(const std::string& uncrypt_path_file, std::string* package_name) {
CHECK(package_name != nullptr);
@@ -167,7 +229,7 @@ static bool find_uncrypt_package(const std::string& uncrypt_path_file, std::stri
}
static int produce_block_map(const char* path, const char* map_file, const char* blk_dev,
- bool encrypted, int status_fd) {
+ bool encrypted, int socket) {
std::string err;
if (!android::base::RemoveFileIfExists(map_file, &err)) {
ALOGE("failed to remove the existing map file %s: %s", map_file, err.c_str());
@@ -181,9 +243,9 @@ static int produce_block_map(const char* path, const char* map_file, const char*
return -1;
}
- // Make sure we can write to the status_file.
- if (!android::base::WriteStringToFd("0\n", status_fd)) {
- ALOGE("failed to update \"%s\"\n", STATUS_FILE.c_str());
+ // Make sure we can write to the socket.
+ if (!write_status_to_socket(0, socket)) {
+ ALOGE("failed to write to socket %d\n", socket);
return -1;
}
@@ -236,8 +298,8 @@ static int produce_block_map(const char* path, const char* map_file, const char*
// Update the status file, progress must be between [0, 99].
int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size)));
if (progress > last_progress) {
- last_progress = progress;
- android::base::WriteStringToFd(std::to_string(progress) + "\n", status_fd);
+ last_progress = progress;
+ write_status_to_socket(progress, socket);
}
if ((tail+1) % WINDOW_SIZE == head) {
@@ -350,54 +412,7 @@ static int produce_block_map(const char* path, const char* map_file, const char*
return 0;
}
-static std::string get_misc_blk_device() {
- struct fstab* fstab = read_fstab();
- if (fstab == nullptr) {
- return "";
- }
- for (int i = 0; i < fstab->num_entries; ++i) {
- fstab_rec* v = &fstab->recs[i];
- if (v->mount_point != nullptr && strcmp(v->mount_point, "/misc") == 0) {
- return v->blk_device;
- }
- }
- return "";
-}
-
-static int write_bootloader_message(const bootloader_message* in) {
- std::string misc_blk_device = get_misc_blk_device();
- if (misc_blk_device.empty()) {
- ALOGE("failed to find /misc partition.");
- return -1;
- }
- android::base::unique_fd fd(open(misc_blk_device.c_str(), O_WRONLY | O_SYNC));
- if (fd == -1) {
- ALOGE("failed to open %s: %s", misc_blk_device.c_str(), strerror(errno));
- return -1;
- }
- if (!android::base::WriteFully(fd, in, sizeof(*in))) {
- ALOGE("failed to write %s: %s", misc_blk_device.c_str(), strerror(errno));
- return -1;
- }
- // TODO: O_SYNC and fsync() duplicates each other?
- if (fsync(fd) == -1) {
- ALOGE("failed to fsync %s: %s", misc_blk_device.c_str(), strerror(errno));
- return -1;
- }
- return 0;
-}
-
-static void reboot_to_recovery() {
- ALOGI("rebooting to recovery");
- property_set("sys.powerctl", "reboot,recovery");
- while (true) {
- pause();
- }
- ALOGE("reboot didn't succeed?");
-}
-
-static int uncrypt(const char* input_path, const char* map_file, int status_fd) {
-
+static int uncrypt(const char* input_path, const char* map_file, const int socket) {
ALOGI("update package is \"%s\"", input_path);
// Turn the name of the file we're supposed to convert into an
@@ -408,10 +423,6 @@ static int uncrypt(const char* input_path, const char* map_file, int status_fd)
return 1;
}
- if (read_fstab() == NULL) {
- return 1;
- }
-
bool encryptable;
bool encrypted;
const char* blk_dev = find_block_device(path, &encryptable, &encrypted);
@@ -435,7 +446,7 @@ static int uncrypt(const char* input_path, const char* map_file, int status_fd)
// and /sdcard we leave the file alone.
if (strncmp(path, "/data/", 6) == 0) {
ALOGI("writing block map %s", map_file);
- if (produce_block_map(path, map_file, blk_dev, encrypted, status_fd) != 0) {
+ if (produce_block_map(path, map_file, blk_dev, encrypted, socket) != 0) {
return 1;
}
}
@@ -443,102 +454,141 @@ static int uncrypt(const char* input_path, const char* map_file, int status_fd)
return 0;
}
-static int uncrypt_wrapper(const char* input_path, const char* map_file,
- const std::string& status_file) {
- // The pipe has been created by the system server.
- android::base::unique_fd status_fd(open(status_file.c_str(),
- O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR));
- if (status_fd == -1) {
- ALOGE("failed to open pipe \"%s\": %s", status_file.c_str(), strerror(errno));
- return 1;
- }
-
+static bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) {
std::string package;
if (input_path == nullptr) {
if (!find_uncrypt_package(UNCRYPT_PATH_FILE, &package)) {
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+ write_status_to_socket(-1, socket);
+ return false;
}
input_path = package.c_str();
}
CHECK(map_file != nullptr);
- int status = uncrypt(input_path, map_file, status_fd);
+ int status = uncrypt(input_path, map_file, socket);
if (status != 0) {
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+ write_status_to_socket(-1, socket);
+ return false;
}
- android::base::WriteStringToFd("100\n", status_fd);
- return 0;
+ write_status_to_socket(100, socket);
+ return true;
}
-static int clear_bcb(const std::string& status_file) {
- android::base::unique_fd status_fd(open(status_file.c_str(),
- O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR));
- if (status_fd == -1) {
- ALOGE("failed to open pipe \"%s\": %s", status_file.c_str(), strerror(errno));
- return 1;
- }
- bootloader_message boot = {};
- if (write_bootloader_message(&boot) != 0) {
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+static bool clear_bcb(const int socket) {
+ std::string err;
+ if (!clear_bootloader_message(&err)) {
+ ALOGE("failed to clear bootloader message: %s", err.c_str());
+ write_status_to_socket(-1, socket);
+ return false;
}
- android::base::WriteStringToFd("100\n", status_fd);
- return 0;
+ write_status_to_socket(100, socket);
+ return true;
}
-static int setup_bcb(const std::string& command_file, const std::string& status_file) {
- android::base::unique_fd status_fd(open(status_file.c_str(),
- O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR));
- if (status_fd == -1) {
- ALOGE("failed to open pipe \"%s\": %s", status_file.c_str(), strerror(errno));
- return 1;
+static bool setup_bcb(const int socket) {
+ // c5. receive message length
+ int length;
+ if (!android::base::ReadFully(socket, &length, 4)) {
+ ALOGE("failed to read the length: %s", strerror(errno));
+ return false;
}
+ length = ntohl(length);
+
+ // c7. receive message
std::string content;
- if (!android::base::ReadFileToString(command_file, &content)) {
- ALOGE("failed to read \"%s\": %s", command_file.c_str(), strerror(errno));
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+ content.resize(length);
+ if (!android::base::ReadFully(socket, &content[0], length)) {
+ ALOGE("failed to read the length: %s", strerror(errno));
+ return false;
}
- bootloader_message boot = {};
- strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
- strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
- strlcat(boot.recovery, content.c_str(), sizeof(boot.recovery));
- if (write_bootloader_message(&boot) != 0) {
- ALOGE("failed to set bootloader message");
- android::base::WriteStringToFd("-1\n", status_fd);
- return 1;
+ ALOGI(" received command: [%s] (%zu)", content.c_str(), content.size());
+
+ // c8. setup the bcb command
+ std::string err;
+ if (!write_bootloader_message({content}, &err)) {
+ ALOGE("failed to set bootloader message: %s", err.c_str());
+ write_status_to_socket(-1, socket);
+ return false;
}
- android::base::WriteStringToFd("100\n", status_fd);
- return 0;
+ // c10. send "100" status
+ write_status_to_socket(100, socket);
+ return true;
}
static void usage(const char* exename) {
fprintf(stderr, "Usage of %s:\n", exename);
fprintf(stderr, "%s [<package_path> <map_file>] Uncrypt ota package.\n", exename);
- fprintf(stderr, "%s --reboot Clear BCB data and reboot to recovery.\n", exename);
fprintf(stderr, "%s --clear-bcb Clear BCB data in misc partition.\n", exename);
fprintf(stderr, "%s --setup-bcb Setup BCB data by command file.\n", exename);
}
int main(int argc, char** argv) {
- if (argc == 2) {
- if (strcmp(argv[1], "--reboot") == 0) {
- reboot_to_recovery();
- } else if (strcmp(argv[1], "--clear-bcb") == 0) {
- return clear_bcb(STATUS_FILE);
- } else if (strcmp(argv[1], "--setup-bcb") == 0) {
- return setup_bcb(COMMAND_FILE, STATUS_FILE);
- }
- } else if (argc == 1 || argc == 3) {
- const char* input_path = nullptr;
- const char* map_file = CACHE_BLOCK_MAP.c_str();
- if (argc == 3) {
- input_path = argv[1];
- map_file = argv[2];
- }
- return uncrypt_wrapper(input_path, map_file, STATUS_FILE);
+ enum { UNCRYPT, SETUP_BCB, CLEAR_BCB } action;
+ const char* input_path = nullptr;
+ const char* map_file = CACHE_BLOCK_MAP.c_str();
+
+ if (argc == 2 && strcmp(argv[1], "--clear-bcb") == 0) {
+ action = CLEAR_BCB;
+ } else if (argc == 2 && strcmp(argv[1], "--setup-bcb") == 0) {
+ action = SETUP_BCB;
+ } else if (argc == 1) {
+ action = UNCRYPT;
+ } else if (argc == 3) {
+ input_path = argv[1];
+ map_file = argv[2];
+ action = UNCRYPT;
+ } else {
+ usage(argv[0]);
+ return 2;
+ }
+
+ if ((fstab = read_fstab()) == nullptr) {
+ return 1;
+ }
+
+ // c3. The socket is created by init when starting the service. uncrypt
+ // will use the socket to communicate with its caller.
+ android::base::unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str()));
+ if (service_socket == -1) {
+ ALOGE("failed to open socket \"%s\": %s", UNCRYPT_SOCKET.c_str(), strerror(errno));
+ return 1;
+ }
+ fcntl(service_socket, F_SETFD, FD_CLOEXEC);
+
+ if (listen(service_socket, 1) == -1) {
+ ALOGE("failed to listen on socket %d: %s", service_socket.get(), strerror(errno));
+ return 1;
+ }
+
+ android::base::unique_fd socket_fd(accept4(service_socket, nullptr, nullptr, SOCK_CLOEXEC));
+ if (socket_fd == -1) {
+ ALOGE("failed to accept on socket %d: %s", service_socket.get(), strerror(errno));
+ return 1;
+ }
+
+ bool success = false;
+ switch (action) {
+ case UNCRYPT:
+ success = uncrypt_wrapper(input_path, map_file, socket_fd);
+ break;
+ case SETUP_BCB:
+ success = setup_bcb(socket_fd);
+ break;
+ case CLEAR_BCB:
+ success = clear_bcb(socket_fd);
+ break;
+ default: // Should never happen.
+ ALOGE("Invalid uncrypt action code: %d", action);
+ return 1;
+ }
+
+ // c13. Read a 4-byte code from the client before uncrypt exits. This is to
+ // ensure the client to receive the last status code before the socket gets
+ // destroyed.
+ int code;
+ if (android::base::ReadFully(socket_fd, &code, 4)) {
+ ALOGI(" received %d, exiting now", code);
+ } else {
+ ALOGE("failed to read the code: %s", strerror(errno));
}
- usage(argv[0]);
- return 2;
+ return success ? 0 : 1;
}
diff --git a/uncrypt/uncrypt.rc b/uncrypt/uncrypt.rc
index b07c1dada..52f564eb6 100644
--- a/uncrypt/uncrypt.rc
+++ b/uncrypt/uncrypt.rc
@@ -1,19 +1,17 @@
service uncrypt /system/bin/uncrypt
class main
- disabled
- oneshot
-
-service pre-recovery /system/bin/uncrypt --reboot
- class main
+ socket uncrypt stream 600 system system
disabled
oneshot
service setup-bcb /system/bin/uncrypt --setup-bcb
class main
+ socket uncrypt stream 600 system system
disabled
oneshot
service clear-bcb /system/bin/uncrypt --clear-bcb
class main
+ socket uncrypt stream 600 system system
disabled
- oneshot \ No newline at end of file
+ oneshot
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 12a549dba..f78342d36 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -44,6 +44,7 @@
#include "applypatch/applypatch.h"
#include "edify/expr.h"
+#include "error_code.h"
#include "install.h"
#include "openssl/sha.h"
#include "minzip/Hash.h"
@@ -68,6 +69,7 @@ struct RangeSet {
std::vector<size_t> pos; // Actual limit is INT_MAX.
};
+static CauseCode failure_type = kNoCause;
static std::map<std::string, RangeSet> stash_map;
static void parse_range(const std::string& range_text, RangeSet& rs) {
@@ -145,6 +147,7 @@ static int read_all(int fd, uint8_t* data, size_t size) {
while (so_far < size) {
ssize_t r = TEMP_FAILURE_RETRY(ota_read(fd, data+so_far, size-so_far));
if (r == -1) {
+ failure_type = kFreadFailure;
fprintf(stderr, "read failed: %s\n", strerror(errno));
return -1;
}
@@ -162,6 +165,7 @@ static int write_all(int fd, const uint8_t* data, size_t size) {
while (written < size) {
ssize_t w = TEMP_FAILURE_RETRY(ota_write(fd, data+written, size-written));
if (w == -1) {
+ failure_type = kFwriteFailure;
fprintf(stderr, "write failed: %s\n", strerror(errno));
return -1;
}
@@ -178,6 +182,7 @@ static int write_all(int fd, const std::vector<uint8_t>& buffer, size_t size) {
static bool check_lseek(int fd, off64_t offset, int whence) {
off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence));
if (rc == -1) {
+ failure_type = kLseekFailure;
fprintf(stderr, "lseek64 failed: %s\n", strerror(errno));
return false;
}
@@ -373,6 +378,7 @@ struct CommandParameters {
bool isunresumable;
int version;
size_t written;
+ size_t stashed;
NewThreadInfo nti;
pthread_t thread;
std::vector<uint8_t> buffer;
@@ -645,6 +651,7 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
}
if (ota_fsync(fd) == -1) {
+ failure_type = kFsyncFailure;
fprintf(stderr, "fsync \"%s\" failed: %s\n", fn.c_str(), strerror(errno));
return -1;
}
@@ -659,11 +666,13 @@ static int WriteStash(const std::string& base, const std::string& id, int blocks
android::base::unique_fd dfd(TEMP_FAILURE_RETRY(ota_open(dname.c_str(),
O_RDONLY | O_DIRECTORY)));
if (dfd == -1) {
+ failure_type = kFileOpenFailure;
fprintf(stderr, "failed to open \"%s\" failed: %s\n", dname.c_str(), strerror(errno));
return -1;
}
if (ota_fsync(dfd) == -1) {
+ failure_type = kFsyncFailure;
fprintf(stderr, "fsync \"%s\" failed: %s\n", dname.c_str(), strerror(errno));
return -1;
}
@@ -692,19 +701,21 @@ static int CreateStash(State* state, int maxblocks, const char* blockdev, std::s
int res = stat(dirname.c_str(), &sb);
if (res == -1 && errno != ENOENT) {
- ErrorAbort(state, "stat \"%s\" failed: %s\n", dirname.c_str(), strerror(errno));
+ ErrorAbort(state, kStashCreationFailure, "stat \"%s\" failed: %s\n",
+ dirname.c_str(), strerror(errno));
return -1;
} else if (res != 0) {
fprintf(stderr, "creating stash %s\n", dirname.c_str());
res = mkdir(dirname.c_str(), STASH_DIRECTORY_MODE);
if (res != 0) {
- ErrorAbort(state, "mkdir \"%s\" failed: %s\n", dirname.c_str(), strerror(errno));
+ ErrorAbort(state, kStashCreationFailure, "mkdir \"%s\" failed: %s\n",
+ dirname.c_str(), strerror(errno));
return -1;
}
if (CacheSizeCheck(maxblocks * BLOCKSIZE) != 0) {
- ErrorAbort(state, "not enough space for stash\n");
+ ErrorAbort(state, kStashCreationFailure, "not enough space for stash\n");
return -1;
}
@@ -724,7 +735,8 @@ static int CreateStash(State* state, int maxblocks, const char* blockdev, std::s
size = maxblocks * BLOCKSIZE - size;
if (size > 0 && CacheSizeCheck(size) != 0) {
- ErrorAbort(state, "not enough space for stash (%d more needed)\n", size);
+ ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%d more needed)\n",
+ size);
return -1;
}
@@ -774,6 +786,7 @@ static int SaveStash(CommandParameters& params, const std::string& base,
}
fprintf(stderr, "stashing %zu blocks to %s\n", blocks, id.c_str());
+ params.stashed += blocks;
return WriteStash(base, id, blocks, buffer, false, nullptr);
}
@@ -970,6 +983,7 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t&
return -1;
}
+ params.stashed += src_blocks;
// Can be deleted when the write has completed
if (!stash_exists) {
params.freestash = srchash;
@@ -1339,19 +1353,21 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
std::unique_ptr<Value, decltype(&FreeValue)> patch_data_fn_holder(patch_data_fn, FreeValue);
if (blockdev_filename->type != VAL_STRING) {
- ErrorAbort(state, "blockdev_filename argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
+ name);
return StringValue(strdup(""));
}
if (transfer_list_value->type != VAL_BLOB) {
- ErrorAbort(state, "transfer_list argument to %s must be blob", name);
+ ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name);
return StringValue(strdup(""));
}
if (new_data_fn->type != VAL_STRING) {
- ErrorAbort(state, "new_data_fn argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name);
return StringValue(strdup(""));
}
if (patch_data_fn->type != VAL_STRING) {
- ErrorAbort(state, "patch_data_fn argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string",
+ name);
return StringValue(strdup(""));
}
@@ -1409,7 +1425,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
const std::string transfer_list(transfer_list_value->data, transfer_list_value->size);
std::vector<std::string> lines = android::base::Split(transfer_list, "\n");
if (lines.size() < 2) {
- ErrorAbort(state, "too few lines in the transfer list [%zd]\n", lines.size());
+ ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]\n",
+ lines.size());
return StringValue(strdup(""));
}
@@ -1424,7 +1441,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
// Second line in transfer list is the total number of blocks we expect to write
int total_blocks;
if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) {
- ErrorAbort(state, "unexpected block count [%s]\n", lines[1].c_str());
+ ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str());
return StringValue(strdup(""));
}
@@ -1435,7 +1452,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
size_t start = 2;
if (params.version >= 2) {
if (lines.size() < 4) {
- ErrorAbort(state, "too few lines in the transfer list [%zu]\n", lines.size());
+ ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n",
+ lines.size());
return StringValue(strdup(""));
}
@@ -1445,7 +1463,8 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
// Fourth line is the maximum number of blocks that will be stashed simultaneously
int stash_max_blocks;
if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) {
- ErrorAbort(state, "unexpected maximum stash blocks [%s]\n", lines[3].c_str());
+ ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n",
+ lines[3].c_str());
return StringValue(strdup(""));
}
@@ -1499,6 +1518,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
if (params.canwrite) {
if (ota_fsync(params.fd) == -1) {
+ failure_type = kFsyncFailure;
fprintf(stderr, "fsync failed: %s\n", strerror(errno));
goto pbiudone;
}
@@ -1511,8 +1531,17 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
pthread_join(params.thread, nullptr);
fprintf(stderr, "wrote %zu blocks; expected %d\n", params.written, total_blocks);
+ fprintf(stderr, "stashed %zu blocks\n", params.stashed);
fprintf(stderr, "max alloc needed was %zu\n", params.buffer.size());
+ const char* partition = strrchr(blockdev_filename->data, '/');
+ if (partition != nullptr && *(partition+1) != 0) {
+ fprintf(cmd_pipe, "log bytes_written_%s: %zu\n", partition + 1,
+ params.written * BLOCKSIZE);
+ fprintf(cmd_pipe, "log bytes_stashed_%s: %zu\n", partition + 1,
+ params.stashed * BLOCKSIZE);
+ fflush(cmd_pipe);
+ }
// Delete stash only after successfully completing the update, as it
// may contain blocks needed to complete the update later.
DeleteStash(params.stashbase);
@@ -1524,6 +1553,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
pbiudone:
if (ota_fsync(params.fd) == -1) {
+ failure_type = kFsyncFailure;
fprintf(stderr, "fsync failed: %s\n", strerror(errno));
}
// params.fd will be automatically closed because it's a unique_fd.
@@ -1534,6 +1564,10 @@ pbiudone:
DeleteStash(params.stashbase);
}
+ if (failure_type != kNoCause && state->cause_code == kNoCause) {
+ state->cause_code = failure_type;
+ }
+
return StringValue(rc == 0 ? strdup("t") : strdup(""));
}
@@ -1639,17 +1673,19 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
FreeValue);
if (blockdev_filename->type != VAL_STRING) {
- ErrorAbort(state, "blockdev_filename argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
+ name);
return StringValue(strdup(""));
}
if (ranges->type != VAL_STRING) {
- ErrorAbort(state, "ranges argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
return StringValue(strdup(""));
}
android::base::unique_fd fd(ota_open(blockdev_filename->data, O_RDWR));
if (fd == -1) {
- ErrorAbort(state, "open \"%s\" failed: %s", blockdev_filename->data, strerror(errno));
+ ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", blockdev_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
@@ -1662,14 +1698,15 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
std::vector<uint8_t> buffer(BLOCKSIZE);
for (size_t i = 0; i < rs.count; ++i) {
if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) {
- ErrorAbort(state, "failed to seek %s: %s", blockdev_filename->data, strerror(errno));
+ ErrorAbort(state, kLseekFailure, "failed to seek %s: %s", blockdev_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) {
if (read_all(fd, buffer, BLOCKSIZE) == -1) {
- ErrorAbort(state, "failed to read %s: %s", blockdev_filename->data,
- strerror(errno));
+ ErrorAbort(state, kFreadFailure, "failed to read %s: %s", blockdev_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
@@ -1696,13 +1733,14 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue);
if (filename->type != VAL_STRING) {
- ErrorAbort(state, "filename argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
return StringValue(strdup(""));
}
android::base::unique_fd fd(ota_open(arg_filename->data, O_RDONLY));
if (fd == -1) {
- ErrorAbort(state, "open \"%s\" failed: %s", arg_filename->data, strerror(errno));
+ ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
@@ -1710,7 +1748,8 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
std::vector<uint8_t> block0_buffer(BLOCKSIZE);
if (ReadBlocks(blk0, block0_buffer, fd) == -1) {
- ErrorAbort(state, "failed to read %s: %s", arg_filename->data, strerror(errno));
+ ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
@@ -1745,11 +1784,11 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
std::unique_ptr<Value, decltype(&FreeValue)> ranges(arg_ranges, FreeValue);
if (filename->type != VAL_STRING) {
- ErrorAbort(state, "filename argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
return StringValue(strdup(""));
}
if (ranges->type != VAL_STRING) {
- ErrorAbort(state, "ranges argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
return StringValue(strdup(""));
}
@@ -1760,19 +1799,20 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
fec::io fh(filename->data, O_RDWR);
if (!fh) {
- ErrorAbort(state, "fec_open \"%s\" failed: %s", filename->data, strerror(errno));
+ ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data,
+ strerror(errno));
return StringValue(strdup(""));
}
if (!fh.has_ecc() || !fh.has_verity()) {
- ErrorAbort(state, "unable to use metadata to correct errors");
+ ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors");
return StringValue(strdup(""));
}
fec_status status;
if (!fh.get_status(status)) {
- ErrorAbort(state, "failed to read FEC status");
+ ErrorAbort(state, kLibfecFailure, "failed to read FEC status");
return StringValue(strdup(""));
}
@@ -1789,8 +1829,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
}
if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) {
- ErrorAbort(state, "failed to recover %s (block %zu): %s", filename->data,
- j, strerror(errno));
+ ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s",
+ filename->data, j, strerror(errno));
return StringValue(strdup(""));
}
diff --git a/updater/install.cpp b/updater/install.cpp
index bab2fe166..a65b32d81 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -48,10 +48,11 @@
#include "cutils/misc.h"
#include "cutils/properties.h"
#include "edify/expr.h"
-#include "openssl/sha.h"
+#include "error_code.h"
#include "minzip/DirUtil.h"
#include "mtdutils/mounts.h"
#include "mtdutils/mtdutils.h"
+#include "openssl/sha.h"
#include "ota_io.h"
#include "updater.h"
#include "install.h"
@@ -114,7 +115,7 @@ char* PrintSha1(const uint8_t* digest) {
Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 4 && argc != 5) {
- return ErrorAbort(state, "%s() expects 4-5 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc);
}
char* fs_type;
char* partition_type;
@@ -137,20 +138,21 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
}
if (strlen(fs_type) == 0) {
- ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
goto done;
}
if (strlen(partition_type) == 0) {
- ErrorAbort(state, "partition_type argument to %s() can't be empty",
+ ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
name);
goto done;
}
if (strlen(location) == 0) {
- ErrorAbort(state, "location argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
goto done;
}
if (strlen(mount_point) == 0) {
- ErrorAbort(state, "mount_point argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
+ name);
goto done;
}
@@ -213,14 +215,14 @@ done:
Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* mount_point;
if (ReadArgs(state, argv, 1, &mount_point) < 0) {
return NULL;
}
if (strlen(mount_point) == 0) {
- ErrorAbort(state, "mount_point argument to unmount() can't be empty");
+ ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty");
goto done;
}
@@ -243,14 +245,14 @@ done:
Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* mount_point;
if (ReadArgs(state, argv, 1, &mount_point) < 0) {
return NULL;
}
if (strlen(mount_point) == 0) {
- ErrorAbort(state, "mount_point argument to unmount() can't be empty");
+ ErrorAbort(state, kArgsParsingFailure, "mount_point argument to unmount() can't be empty");
goto done;
}
@@ -301,7 +303,7 @@ static int exec_cmd(const char* path, char* const argv[]) {
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 5) {
- return ErrorAbort(state, "%s() expects 5 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc);
}
char* fs_type;
char* partition_type;
@@ -314,21 +316,22 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
}
if (strlen(fs_type) == 0) {
- ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
goto done;
}
if (strlen(partition_type) == 0) {
- ErrorAbort(state, "partition_type argument to %s() can't be empty",
+ ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
name);
goto done;
}
if (strlen(location) == 0) {
- ErrorAbort(state, "location argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
goto done;
}
if (strlen(mount_point) == 0) {
- ErrorAbort(state, "mount_point argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
+ name);
goto done;
}
@@ -403,7 +406,7 @@ done:
Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* src_name;
@@ -413,21 +416,21 @@ Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
return NULL;
}
if (strlen(src_name) == 0) {
- ErrorAbort(state, "src_name argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name);
goto done;
}
if (strlen(dst_name) == 0) {
- ErrorAbort(state, "dst_name argument to %s() can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name);
goto done;
}
if (make_parents(dst_name) != 0) {
- ErrorAbort(state, "Creating parent of %s failed, error %s",
+ ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s",
dst_name, strerror(errno));
} else if (access(dst_name, F_OK) == 0 && access(src_name, F_OK) != 0) {
// File was already moved
result = dst_name;
} else if (rename(src_name, dst_name) != 0) {
- ErrorAbort(state, "Rename of %s to %s failed, error %s",
+ ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s",
src_name, dst_name, strerror(errno));
} else {
result = dst_name;
@@ -470,7 +473,7 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* frac_str;
char* sec_str;
@@ -491,7 +494,7 @@ Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* frac_str;
if (ReadArgs(state, argv, 1, &frac_str) < 0) {
@@ -510,7 +513,7 @@ Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* PackageExtractDirFn(const char* name, State* state,
int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* zip_path;
char* dest_path;
@@ -538,7 +541,7 @@ Value* PackageExtractDirFn(const char* name, State* state,
Value* PackageExtractFileFn(const char* name, State* state,
int argc, Expr* argv[]) {
if (argc < 1 || argc > 2) {
- return ErrorAbort(state, "%s() expects 1 or 2 args, got %d",
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d",
name, argc);
}
bool success = false;
@@ -646,7 +649,7 @@ static int make_parents(char* name) {
// unlinks any previously existing src1, src2, etc before creating symlinks.
Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc == 0) {
- return ErrorAbort(state, "%s() expects 1+ args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc);
}
char* target;
target = Evaluate(state, argv[0]);
@@ -682,7 +685,7 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
}
free(srcs);
if (bad) {
- return ErrorAbort(state, "%s: some symlinks failed", name);
+ return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name);
}
return StringValue(strdup(""));
}
@@ -906,14 +909,16 @@ static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv
bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
if ((argc % 2) != 1) {
- return ErrorAbort(state, "%s() expects an odd number of arguments, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure,
+ "%s() expects an odd number of arguments, got %d", name, argc);
}
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) return NULL;
if (lstat(args[0], &sb) == -1) {
- result = ErrorAbort(state, "%s: Error on lstat of \"%s\": %s", name, args[0], strerror(errno));
+ result = ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s",
+ name, args[0], strerror(errno));
goto done;
}
@@ -942,7 +947,7 @@ done:
}
if (bad > 0) {
- return ErrorAbort(state, "%s: some changes failed", name);
+ return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
}
return StringValue(strdup(""));
@@ -950,7 +955,7 @@ done:
Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* key = Evaluate(state, argv[0]);
if (key == NULL) return NULL;
@@ -979,20 +984,22 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
struct stat st;
if (stat(filename, &st) < 0) {
- ErrorAbort(state, "%s: failed to stat \"%s\": %s", name, filename, strerror(errno));
+ ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name, filename,
+ strerror(errno));
goto done;
}
#define MAX_FILE_GETPROP_SIZE 65536
if (st.st_size > MAX_FILE_GETPROP_SIZE) {
- ErrorAbort(state, "%s too large for %s (max %d)", filename, name, MAX_FILE_GETPROP_SIZE);
+ ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %d)", filename, name,
+ MAX_FILE_GETPROP_SIZE);
goto done;
}
buffer = reinterpret_cast<char*>(malloc(st.st_size+1));
if (buffer == NULL) {
- ErrorAbort(state, "%s: failed to alloc %zu bytes", name,
+ ErrorAbort(state, kFileGetPropFailure, "%s: failed to alloc %zu bytes", name,
static_cast<size_t>(st.st_size+1));
goto done;
}
@@ -1000,12 +1007,13 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
FILE* f;
f = ota_fopen(filename, "rb");
if (f == NULL) {
- ErrorAbort(state, "%s: failed to open %s: %s", name, filename, strerror(errno));
+ ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename,
+ strerror(errno));
goto done;
}
if (ota_fread(buffer, 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
- ErrorAbort(state, "%s: failed to read %zu bytes from %s",
+ ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s",
name, static_cast<size_t>(st.st_size), filename);
ota_fclose(f);
goto done;
@@ -1071,16 +1079,16 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
char* partition = NULL;
if (partition_value->type != VAL_STRING) {
- ErrorAbort(state, "partition argument to %s must be string", name);
+ ErrorAbort(state, kArgsParsingFailure, "partition argument to %s must be string", name);
goto done;
}
partition = partition_value->data;
if (strlen(partition) == 0) {
- ErrorAbort(state, "partition argument to %s can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "partition argument to %s can't be empty", name);
goto done;
}
if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) {
- ErrorAbort(state, "file argument to %s can't be empty", name);
+ ErrorAbort(state, kArgsParsingFailure, "file argument to %s can't be empty", name);
goto done;
}
@@ -1161,7 +1169,8 @@ Value* ApplyPatchSpaceFn(const char* name, State* state,
size_t bytes;
if (!android::base::ParseUint(bytes_str, &bytes)) {
- ErrorAbort(state, "%s(): can't parse \"%s\" as byte count\n\n", name, bytes_str);
+ ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n",
+ name, bytes_str);
free(bytes_str);
return nullptr;
}
@@ -1173,9 +1182,8 @@ Value* ApplyPatchSpaceFn(const char* name, State* state,
Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc < 6 || (argc % 2) == 1) {
- return ErrorAbort(state, "%s(): expected at least 6 args and an "
- "even number, got %d",
- name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an "
+ "even number, got %d", name, argc);
}
char* source_filename;
@@ -1189,7 +1197,8 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
size_t target_size;
if (!android::base::ParseUint(target_size_str, &target_size)) {
- ErrorAbort(state, "%s(): can't parse \"%s\" as byte count", name, target_size_str);
+ ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count",
+ name, target_size_str);
free(source_filename);
free(target_filename);
free(target_sha1);
@@ -1213,11 +1222,11 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
for (int i = 0; i < patchcount; ++i) {
if (patch_shas[i]->type != VAL_STRING) {
- ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i);
+ ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, i);
return nullptr;
}
if (patches[i]->type != VAL_BLOB) {
- ErrorAbort(state, "%s(): patch #%d is not blob", name, i);
+ ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, i);
return nullptr;
}
}
@@ -1240,7 +1249,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* ApplyPatchCheckFn(const char* name, State* state,
int argc, Expr* argv[]) {
if (argc < 1) {
- return ErrorAbort(state, "%s(): expected at least 1 arg, got %d",
+ return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d",
name, argc);
}
@@ -1285,7 +1294,7 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 0) {
- return ErrorAbort(state, "%s() expects no args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
}
fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n");
return StringValue(strdup("t"));
@@ -1293,7 +1302,7 @@ Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc < 1) {
- return ErrorAbort(state, "%s() expects at least 1 arg", name);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
}
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) {
@@ -1347,7 +1356,7 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
//
Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc < 1) {
- return ErrorAbort(state, "%s() expects at least 1 arg", name);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
}
std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free);
@@ -1395,7 +1404,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
// is actually a FileContents*).
Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* filename;
if (ReadArgs(state, argv, 1, &filename) < 0) return NULL;
@@ -1431,7 +1440,7 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
// partition.
Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* filename;
@@ -1457,7 +1466,7 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
sleep(5);
free(property);
- ErrorAbort(state, "%s() failed to reboot", name);
+ ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
return NULL;
}
@@ -1473,7 +1482,7 @@ Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
// bytes.
Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* filename;
@@ -1503,7 +1512,7 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
// is the block device for the misc partition.
Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
- return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
}
char* filename;
@@ -1521,7 +1530,7 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) {
- return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
}
char* filename;
@@ -1543,7 +1552,7 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[])
Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 0) {
- return ErrorAbort(state, "%s() expects no args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
}
UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
fprintf(ui->cmd_pipe, "enable_reboot\n");
@@ -1552,12 +1561,12 @@ Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc == 0) {
- return ErrorAbort(state, "%s() expects args, got %d", name, argc);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc);
}
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) {
- return ErrorAbort(state, "%s() could not read args", name);
+ return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
}
char** args2 = reinterpret_cast<char**>(malloc(sizeof(char*) * (argc+1)));
@@ -1575,7 +1584,8 @@ Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
free(args2[0]);
free(args2);
if (result != 0) {
- return ErrorAbort(state, "%s() returned error code %d", name, result);
+ return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d",
+ name, result);
}
return StringValue(strdup("t"));
}
diff --git a/updater/updater.cpp b/updater/updater.cpp
index 0497d6a85..f51a6db73 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -159,11 +159,28 @@ int main(int argc, char** argv) {
printf("script aborted: %s\n", state.errmsg);
char* line = strtok(state.errmsg, "\n");
while (line) {
+ // Parse the error code in abort message.
+ // Example: "E30: This package is for bullhead devices."
+ if (*line == 'E') {
+ if (sscanf(line, "E%u: ", &state.error_code) != 1) {
+ printf("Failed to parse error code: [%s]\n", line);
+ }
+ }
fprintf(cmd_pipe, "ui_print %s\n", line);
line = strtok(NULL, "\n");
}
fprintf(cmd_pipe, "ui_print\n");
}
+
+ if (state.error_code != kNoError) {
+ fprintf(cmd_pipe, "log error: %d\n", state.error_code);
+ // Cause code should provide additional information about the abort;
+ // report only when an error exists.
+ if (state.cause_code != kNoCause) {
+ fprintf(cmd_pipe, "log cause: %d\n", state.cause_code);
+ }
+ }
+
free(state.errmsg);
return 7;
} else {
diff --git a/verifier.cpp b/verifier.cpp
index 1d6cf811a..996a1fdf9 100644
--- a/verifier.cpp
+++ b/verifier.cpp
@@ -28,11 +28,14 @@
#include "asn1_decoder.h"
#include "common.h"
+#include "print_sha1.h"
#include "ui.h"
#include "verifier.h"
extern RecoveryUI* ui;
+static constexpr size_t MiB = 1024 * 1024;
+
/*
* Simple version of PKCS#7 SignedData extraction. This extracts the
* signature OCTET STRING to be used for signature verification.
@@ -188,8 +191,6 @@ int verify_file(unsigned char* addr, size_t length,
}
}
-#define BUFFER_SIZE 4096
-
bool need_sha1 = false;
bool need_sha256 = false;
for (const auto& key : keys) {
@@ -207,8 +208,10 @@ int verify_file(unsigned char* addr, size_t length,
double frac = -1.0;
size_t so_far = 0;
while (so_far < signed_len) {
- size_t size = signed_len - so_far;
- if (size > BUFFER_SIZE) size = BUFFER_SIZE;
+ // On a Nexus 5X, experiment showed 16MiB beat 1MiB by 6% faster for a
+ // 1196MiB full OTA and 60% for an 89MiB incremental OTA.
+ // http://b/28135231.
+ size_t size = std::min(signed_len - so_far, 16 * MiB);
if (need_sha1) SHA1_Update(&sha1_ctx, addr + so_far, size);
if (need_sha256) SHA256_Update(&sha256_ctx, addr + so_far, size);
@@ -229,9 +232,14 @@ int verify_file(unsigned char* addr, size_t length,
uint8_t* sig_der = nullptr;
size_t sig_der_length = 0;
+ uint8_t* signature = eocd + eocd_size - signature_start;
size_t signature_size = signature_start - FOOTER_SIZE;
- if (!read_pkcs7(eocd + eocd_size - signature_start, signature_size, &sig_der,
- &sig_der_length)) {
+
+ LOGI("signature (offset: 0x%zx, length: %zu): %s\n",
+ length - signature_start, signature_size,
+ print_hex(signature, signature_size).c_str());
+
+ if (!read_pkcs7(signature, signature_size, &sig_der, &sig_der_length)) {
LOGE("Could not find signature DER block\n");
return VERIFY_FAILURE;
}
@@ -286,6 +294,13 @@ int verify_file(unsigned char* addr, size_t length,
}
i++;
}
+
+ if (need_sha1) {
+ LOGI("SHA-1 digest: %s\n", print_hex(sha1, SHA_DIGEST_LENGTH).c_str());
+ }
+ if (need_sha256) {
+ LOGI("SHA-256 digest: %s\n", print_hex(sha256, SHA256_DIGEST_LENGTH).c_str());
+ }
free(sig_der);
LOGE("failed to verify whole-file signature\n");
return VERIFY_FAILURE;
diff --git a/wear_touch.cpp b/wear_touch.cpp
new file mode 100644
index 000000000..f22d40b88
--- /dev/null
+++ b/wear_touch.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+#include "common.h"
+#include "wear_touch.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <linux/input.h>
+
+#define DEVICE_PATH "/dev/input"
+
+WearSwipeDetector::WearSwipeDetector(int low, int high, OnSwipeCallback callback, void* cookie):
+ mLowThreshold(low),
+ mHighThreshold(high),
+ mCallback(callback),
+ mCookie(cookie),
+ mCurrentSlot(-1) {
+ pthread_create(&mThread, NULL, touch_thread, this);
+}
+
+WearSwipeDetector::~WearSwipeDetector() {
+}
+
+void WearSwipeDetector::detect(int dx, int dy) {
+ enum SwipeDirection direction;
+
+ if (abs(dy) < mLowThreshold && abs(dx) > mHighThreshold) {
+ direction = dx < 0 ? LEFT : RIGHT;
+ } else if (abs(dx) < mLowThreshold && abs(dy) > mHighThreshold) {
+ direction = dy < 0 ? UP : DOWN;
+ } else {
+ LOGD("Ignore %d %d\n", dx, dy);
+ return;
+ }
+
+ LOGD("Swipe direction=%d\n", direction);
+ mCallback(mCookie, direction);
+}
+
+void WearSwipeDetector::process(struct input_event *event) {
+ if (mCurrentSlot < 0) {
+ mCallback(mCookie, UP);
+ mCurrentSlot = 0;
+ }
+
+ if (event->type == EV_ABS) {
+ if (event->code == ABS_MT_SLOT)
+ mCurrentSlot = event->value;
+
+ // Ignore other fingers
+ if (mCurrentSlot > 0) {
+ return;
+ }
+
+ switch (event->code) {
+ case ABS_MT_POSITION_X:
+ mX = event->value;
+ mFingerDown = true;
+ break;
+
+ case ABS_MT_POSITION_Y:
+ mY = event->value;
+ mFingerDown = true;
+ break;
+
+ case ABS_MT_TRACKING_ID:
+ if (event->value < 0)
+ mFingerDown = false;
+ break;
+ }
+ } else if (event->type == EV_SYN) {
+ if (event->code == SYN_REPORT) {
+ if (mFingerDown && !mSwiping) {
+ mStartX = mX;
+ mStartY = mY;
+ mSwiping = true;
+ } else if (!mFingerDown && mSwiping) {
+ mSwiping = false;
+ detect(mX - mStartX, mY - mStartY);
+ }
+ }
+ }
+}
+
+void WearSwipeDetector::run() {
+ int fd = findDevice(DEVICE_PATH);
+ if (fd < 0) {
+ LOGE("no input devices found\n");
+ return;
+ }
+
+ struct input_event event;
+ while (read(fd, &event, sizeof(event)) == sizeof(event)) {
+ process(&event);
+ }
+
+ close(fd);
+}
+
+void* WearSwipeDetector::touch_thread(void* cookie) {
+ ((WearSwipeDetector*)cookie)->run();
+ return NULL;
+}
+
+#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
+
+int WearSwipeDetector::openDevice(const char *device) {
+ int fd = open(device, O_RDONLY);
+ if (fd < 0) {
+ LOGE("could not open %s, %s\n", device, strerror(errno));
+ return false;
+ }
+
+ char name[80];
+ name[sizeof(name) - 1] = '\0';
+ if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
+ LOGE("could not get device name for %s, %s\n", device, strerror(errno));
+ name[0] = '\0';
+ }
+
+ uint8_t bits[512];
+ memset(bits, 0, sizeof(bits));
+ int ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
+ if (ret > 0) {
+ if (test_bit(ABS_MT_POSITION_X, bits) && test_bit(ABS_MT_POSITION_Y, bits)) {
+ LOGD("Found %s %s\n", device, name);
+ return fd;
+ }
+ }
+
+ close(fd);
+ return -1;
+}
+
+int WearSwipeDetector::findDevice(const char* path) {
+ DIR* dir = opendir(path);
+ if (dir == NULL) {
+ LOGE("Could not open directory %s", path);
+ return false;
+ }
+
+ struct dirent* entry;
+ int ret = -1;
+ while (ret < 0 && (entry = readdir(dir)) != NULL) {
+ if (entry->d_name[0] == '.') continue;
+
+ char device[PATH_MAX];
+ device[PATH_MAX-1] = '\0';
+ snprintf(device, PATH_MAX-1, "%s/%s", path, entry->d_name);
+
+ ret = openDevice(device);
+ }
+
+ closedir(dir);
+ return ret;
+}
+
diff --git a/wear_touch.h b/wear_touch.h
new file mode 100644
index 000000000..9a1d3150c
--- /dev/null
+++ b/wear_touch.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef __WEAR_TOUCH_H
+#define __WEAR_TOUCH_H
+
+#include <pthread.h>
+
+class WearSwipeDetector {
+
+public:
+ enum SwipeDirection { UP, DOWN, RIGHT, LEFT };
+ typedef void (*OnSwipeCallback)(void* cookie, enum SwipeDirection direction);
+
+ WearSwipeDetector(int low, int high, OnSwipeCallback cb, void* cookie);
+ ~WearSwipeDetector();
+
+private:
+ void run();
+ void process(struct input_event *event);
+ void detect(int dx, int dy);
+
+ pthread_t mThread;
+ static void* touch_thread(void* cookie);
+
+ int findDevice(const char* path);
+ int openDevice(const char* device);
+
+ int mLowThreshold;
+ int mHighThreshold;
+
+ OnSwipeCallback mCallback;
+ void *mCookie;
+
+ int mX;
+ int mY;
+ int mStartX;
+ int mStartY;
+
+ int mCurrentSlot;
+ bool mFingerDown;
+ bool mSwiping;
+};
+
+#endif // __WEAR_TOUCH_H
diff --git a/wear_ui.cpp b/wear_ui.cpp
index 48278ff21..5451ed1aa 100644
--- a/wear_ui.cpp
+++ b/wear_ui.cpp
@@ -16,9 +16,7 @@
#include <errno.h>
#include <fcntl.h>
-#include <pthread.h>
#include <stdarg.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -31,14 +29,10 @@
#include "common.h"
#include "device.h"
-#include "minui/minui.h"
#include "wear_ui.h"
-#include "ui.h"
#include "cutils/properties.h"
#include "android-base/strings.h"
-
-static int char_width;
-static int char_height;
+#include "android-base/stringprintf.h"
// There's only (at most) one of these objects, and global callbacks
// (for pthread_create, and the input event system) need to find it,
@@ -65,7 +59,6 @@ WearRecoveryUI::WearRecoveryUI() :
currentIcon(NONE),
intro_done(false),
current_frame(0),
- rtl_locale(false),
progressBarType(EMPTY),
progressScopeStart(0),
progressScopeSize(0),
@@ -84,7 +77,6 @@ WearRecoveryUI::WearRecoveryUI() :
for (size_t i = 0; i < 5; i++)
backgroundIcon[i] = NULL;
- pthread_mutex_init(&updateMutex, NULL);
self = this;
}
@@ -148,41 +140,6 @@ void WearRecoveryUI::draw_progress_locked()
}
}
-void WearRecoveryUI::SetColor(UIElement e) {
- switch (e) {
- case HEADER:
- gr_color(247, 0, 6, 255);
- break;
- case MENU:
- case MENU_SEL_BG:
- gr_color(0, 106, 157, 255);
- break;
- case MENU_SEL_FG:
- gr_color(255, 255, 255, 255);
- break;
- case LOG:
- gr_color(249, 194, 0, 255);
- break;
- case TEXT_FILL:
- gr_color(0, 0, 0, 160);
- break;
- default:
- gr_color(255, 255, 255, 255);
- break;
- }
-}
-
-void WearRecoveryUI::DrawTextLine(int x, int* y, const char* line, bool bold) {
- gr_text(x, *y, line, bold);
- *y += char_height + 4;
-}
-
-void WearRecoveryUI::DrawTextLines(int x, int* y, const char* const* lines) {
- for (size_t i = 0; lines != nullptr && lines[i] != nullptr; ++i) {
- DrawTextLine(x, y, lines[i], false);
- }
-}
-
static const char* HEADERS[] = {
"Swipe up/down to move.",
"Swipe left/right to select.",
@@ -221,7 +178,7 @@ void WearRecoveryUI::draw_screen_locked()
if (menu_items > menu_end - menu_start) {
sprintf(cur_selection_str, "Current item: %d/%d", menu_sel + 1, menu_items);
gr_text(x+4, y, cur_selection_str, 1);
- y += char_height+4;
+ y += char_height_+4;
}
// Menu begins here
@@ -232,7 +189,7 @@ void WearRecoveryUI::draw_screen_locked()
if (i == menu_sel) {
// draw the highlight bar
SetColor(MENU_SEL_BG);
- gr_fill(x, y-2, gr_fb_width()-x, y+char_height+2);
+ gr_fill(x, y-2, gr_fb_width()-x, y+char_height_+2);
// white text of selected item
SetColor(MENU_SEL_FG);
if (menu[i][0]) gr_text(x+4, y, menu[i], 1);
@@ -240,7 +197,7 @@ void WearRecoveryUI::draw_screen_locked()
} else {
if (menu[i][0]) gr_text(x+4, y, menu[i], 0);
}
- y += char_height+4;
+ y += char_height_+4;
}
SetColor(MENU);
y += 4;
@@ -256,9 +213,9 @@ void WearRecoveryUI::draw_screen_locked()
int ty;
int row = (text_top+text_rows-1) % text_rows;
size_t count = 0;
- for (int ty = gr_fb_height() - char_height - outer_height;
+ for (int ty = gr_fb_height() - char_height_ - outer_height;
ty > y+2 && count < text_rows;
- ty -= char_height, ++count) {
+ ty -= char_height_, ++count) {
gr_text(x+4, ty, text[row], 0);
--row;
if (row < 0) row = text_rows-1;
@@ -324,26 +281,19 @@ void WearRecoveryUI::progress_loop() {
}
}
-void WearRecoveryUI::LoadBitmap(const char* filename, GRSurface** surface) {
- int result = res_create_display_surface(filename, surface);
- if (result < 0) {
- LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
- }
-}
-
void WearRecoveryUI::Init()
{
gr_init();
- gr_font_size(&char_width, &char_height);
+ gr_font_size(&char_width_, &char_height_);
text_col = text_row = 0;
- text_rows = (gr_fb_height()) / char_height;
- visible_text_rows = (gr_fb_height() - (outer_height * 2)) / char_height;
+ text_rows = (gr_fb_height()) / char_height_;
+ visible_text_rows = (gr_fb_height() - (outer_height * 2)) / char_height_;
if (text_rows > kMaxRows) text_rows = kMaxRows;
text_top = 1;
- text_cols = (gr_fb_width() - (outer_width * 2)) / char_width;
+ text_cols = (gr_fb_width() - (outer_width * 2)) / char_width_;
if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);
@@ -369,29 +319,6 @@ void WearRecoveryUI::Init()
RecoveryUI::Init();
}
-void WearRecoveryUI::SetLocale(const char* locale) {
- if (locale) {
- char* lang = strdup(locale);
- for (char* p = lang; *p; ++p) {
- if (*p == '_') {
- *p = '\0';
- break;
- }
- }
-
- // A bit cheesy: keep an explicit list of supported languages
- // that are RTL.
- if (strcmp(lang, "ar") == 0 || // Arabic
- strcmp(lang, "fa") == 0 || // Persian (Farsi)
- strcmp(lang, "he") == 0 || // Hebrew (new language code)
- strcmp(lang, "iw") == 0 || // Hebrew (old language code)
- strcmp(lang, "ur") == 0) { // Urdu
- rtl_locale = true;
- }
- free(lang);
- }
-}
-
void WearRecoveryUI::SetBackground(Icon icon)
{
pthread_mutex_lock(&updateMutex);
@@ -653,3 +580,35 @@ void WearRecoveryUI::ClearText() {
}
pthread_mutex_unlock(&updateMutex);
}
+
+void WearRecoveryUI::PrintOnScreenOnly(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ PrintV(fmt, false, ap);
+ va_end(ap);
+}
+
+void WearRecoveryUI::PrintV(const char* fmt, bool copy_to_stdout, va_list ap) {
+ std::string str;
+ android::base::StringAppendV(&str, fmt, ap);
+
+ if (copy_to_stdout) {
+ fputs(str.c_str(), stdout);
+ }
+
+ pthread_mutex_lock(&updateMutex);
+ if (text_rows > 0 && text_cols > 0) {
+ for (const char* ptr = str.c_str(); *ptr != '\0'; ++ptr) {
+ if (*ptr == '\n' || text_col >= text_cols) {
+ text[text_row][text_col] = '\0';
+ text_col = 0;
+ text_row = (text_row + 1) % text_rows;
+ if (text_row == text_top) text_top = (text_top + 1) % text_rows;
+ }
+ if (*ptr != '\n') text[text_row][text_col++] = *ptr;
+ }
+ text[text_row][text_col] = '\0';
+ update_screen_locked();
+ }
+ pthread_mutex_unlock(&updateMutex);
+}
diff --git a/wear_ui.h b/wear_ui.h
index 63c1b6e6e..e2d6fe072 100644
--- a/wear_ui.h
+++ b/wear_ui.h
@@ -17,19 +17,13 @@
#ifndef RECOVERY_WEAR_UI_H
#define RECOVERY_WEAR_UI_H
-#include <pthread.h>
-#include <stdio.h>
+#include "screen_ui.h"
-#include "ui.h"
-#include "minui/minui.h"
-
-class WearRecoveryUI : public RecoveryUI {
+class WearRecoveryUI : public ScreenRecoveryUI {
public:
WearRecoveryUI();
void Init();
- void SetLocale(const char* locale);
-
// overall recovery state ("background image")
void SetBackground(Icon icon);
@@ -47,6 +41,7 @@ class WearRecoveryUI : public RecoveryUI {
// printing messages
void Print(const char* fmt, ...);
+ void PrintOnScreenOnly(const char* fmt, ...) __printflike(2, 3);
void ShowFile(const char* filename);
void ShowFile(FILE* fp);
@@ -58,9 +53,6 @@ class WearRecoveryUI : public RecoveryUI {
void Redraw();
- enum UIElement { HEADER, MENU, MENU_SEL_BG, MENU_SEL_FG, LOG, TEXT_FILL };
- virtual void SetColor(UIElement e);
-
protected:
int progress_bar_height, progress_bar_width;
@@ -89,9 +81,6 @@ class WearRecoveryUI : public RecoveryUI {
int current_frame;
- bool rtl_locale;
-
- pthread_mutex_t updateMutex;
GRSurface* backgroundIcon[5];
GRSurface* *introFrames;
GRSurface* *loopFrames;
@@ -128,11 +117,9 @@ class WearRecoveryUI : public RecoveryUI {
void update_screen_locked();
static void* progress_thread(void* cookie);
void progress_loop();
- void LoadBitmap(const char* filename, GRSurface** surface);
void PutChar(char);
void ClearText();
- void DrawTextLine(int x, int* y, const char* line, bool bold);
- void DrawTextLines(int x, int* y, const char* const* lines);
+ void PrintV(const char*, bool, va_list);
};
#endif // RECOVERY_WEAR_UI_H