From a48c494f138ddb99320583d00120674be1e3297c Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Wed, 19 Jul 2017 18:51:03 +0900 Subject: Build libminui with BOARD_VNDK_VERSION Use libdrm_platform which is a platform variant of libdrm. Bug: 63741047 Bug: 37342627 Test: BOARD_VNDK_VERSION=current m -j libminui Test: ryu recovery graphics test shows various graphics Change-Id: Ifd2c1432781a96538585cdf818aa728d628a2f5a --- minui/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minui/Android.mk b/minui/Android.mk index 4dfc65f8a..6522fcfd2 100644 --- a/minui/Android.mk +++ b/minui/Android.mk @@ -25,7 +25,7 @@ LOCAL_SRC_FILES := \ LOCAL_WHOLE_STATIC_LIBRARIES := \ libadf \ - libdrm \ + libdrm_platform \ libsync_recovery LOCAL_STATIC_LIBRARIES := \ -- cgit v1.2.3 From 616256e7398db7432822dde42d0f4e343961f934 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Sat, 12 Aug 2017 06:53:13 -0700 Subject: Import translations. DO NOT MERGE Change-Id: I99a2cf060c75a70b3baf3c22d538fbfa08828474 Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- tools/recovery_l10n/res/values-az/strings.xml | 9 --------- tools/recovery_l10n/res/values-b+sr+Latn/strings.xml | 9 --------- tools/recovery_l10n/res/values-be/strings.xml | 9 --------- tools/recovery_l10n/res/values-bs/strings.xml | 9 --------- tools/recovery_l10n/res/values-en-rAU/strings.xml | 9 --------- tools/recovery_l10n/res/values-gu/strings.xml | 9 --------- tools/recovery_l10n/res/values-kk/strings.xml | 9 --------- tools/recovery_l10n/res/values-kn/strings.xml | 9 --------- tools/recovery_l10n/res/values-mr/strings.xml | 4 ++-- tools/recovery_l10n/res/values-pa/strings.xml | 9 --------- tools/recovery_l10n/res/values-pt-rBR/strings.xml | 9 --------- tools/recovery_l10n/res/values-sq/strings.xml | 9 --------- tools/recovery_l10n/res/values-te/strings.xml | 9 --------- tools/recovery_l10n/res/values-ur/strings.xml | 9 --------- tools/recovery_l10n/res/values-uz/strings.xml | 9 --------- 15 files changed, 2 insertions(+), 128 deletions(-) delete mode 100644 tools/recovery_l10n/res/values-az/strings.xml delete mode 100644 tools/recovery_l10n/res/values-b+sr+Latn/strings.xml delete mode 100644 tools/recovery_l10n/res/values-be/strings.xml delete mode 100644 tools/recovery_l10n/res/values-bs/strings.xml delete mode 100644 tools/recovery_l10n/res/values-en-rAU/strings.xml delete mode 100644 tools/recovery_l10n/res/values-gu/strings.xml delete mode 100644 tools/recovery_l10n/res/values-kk/strings.xml delete mode 100644 tools/recovery_l10n/res/values-kn/strings.xml delete mode 100644 tools/recovery_l10n/res/values-pa/strings.xml delete mode 100644 tools/recovery_l10n/res/values-pt-rBR/strings.xml delete mode 100644 tools/recovery_l10n/res/values-sq/strings.xml delete mode 100644 tools/recovery_l10n/res/values-te/strings.xml delete mode 100644 tools/recovery_l10n/res/values-ur/strings.xml delete mode 100644 tools/recovery_l10n/res/values-uz/strings.xml diff --git a/tools/recovery_l10n/res/values-az/strings.xml b/tools/recovery_l10n/res/values-az/strings.xml deleted file mode 100644 index c6765a9ea..000000000 --- a/tools/recovery_l10n/res/values-az/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Sistem güncəlləməsi quraşdırılır..." - "Silinir" - "Əmr yoxdur" - "Xəta!" - "Təhlükəsizlik güncəlləməsi yüklənir" - diff --git a/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml b/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml deleted file mode 100644 index c2d8f2239..000000000 --- a/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Ažuriranje sistema se instalira" - "Briše se" - "Nema komande" - "Greška!" - "Instalira se bezbednosno ažuriranje" - diff --git a/tools/recovery_l10n/res/values-be/strings.xml b/tools/recovery_l10n/res/values-be/strings.xml deleted file mode 100644 index 7c0954d31..000000000 --- a/tools/recovery_l10n/res/values-be/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Усталёўка абнаўлення сістэмы" - "Сціранне" - "Няма каманды" - "Памылка" - "Усталёўка абнаўлення сістэмы бяспекі" - diff --git a/tools/recovery_l10n/res/values-bs/strings.xml b/tools/recovery_l10n/res/values-bs/strings.xml deleted file mode 100644 index 412cf0276..000000000 --- a/tools/recovery_l10n/res/values-bs/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Ažuriranje sistema…" - "Brisanje u toku" - "Nema komande" - "Greška!" - "Instaliranje sigurnosnog ažuriranja…" - diff --git a/tools/recovery_l10n/res/values-en-rAU/strings.xml b/tools/recovery_l10n/res/values-en-rAU/strings.xml deleted file mode 100644 index dc75c2374..000000000 --- a/tools/recovery_l10n/res/values-en-rAU/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Installing system update" - "Erasing" - "No command" - "Error!" - "Installing security update" - diff --git a/tools/recovery_l10n/res/values-gu/strings.xml b/tools/recovery_l10n/res/values-gu/strings.xml deleted file mode 100644 index 2355a0f4f..000000000 --- a/tools/recovery_l10n/res/values-gu/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "સિસ્ટમ અપડેટ ઇન્સ્ટૉલ કરી રહ્યાં છે" - "કાઢી નાખી રહ્યું છે" - "કોઈ આદેશ નથી" - "ભૂલ!" - "સુરક્ષા અપડેટ ઇન્સ્ટૉલ કરી રહ્યાં છે" - diff --git a/tools/recovery_l10n/res/values-kk/strings.xml b/tools/recovery_l10n/res/values-kk/strings.xml deleted file mode 100644 index a4bd86e66..000000000 --- a/tools/recovery_l10n/res/values-kk/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Жүйе жаңартуы орнатылуда" - "Өшірілуде" - "Пәрмен жоқ" - "Қате!" - "Қауіпсіздік жаңартуы орнатылуда" - diff --git a/tools/recovery_l10n/res/values-kn/strings.xml b/tools/recovery_l10n/res/values-kn/strings.xml deleted file mode 100644 index 5bf6260ee..000000000 --- a/tools/recovery_l10n/res/values-kn/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "ಸಿಸ್ಟಂ ಅಪ್‌ಡೇಟ್‌ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ" - "ಅಳಿಸಲಾಗುತ್ತಿದೆ" - "ಯಾವುದೇ ಆದೇಶವಿಲ್ಲ" - "ದೋಷ!" - "ಭದ್ರತೆಯ ಅಪ್‌ಡೇಟ್‌ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ" - diff --git a/tools/recovery_l10n/res/values-mr/strings.xml b/tools/recovery_l10n/res/values-mr/strings.xml index 8cf86f773..017a515c0 100644 --- a/tools/recovery_l10n/res/values-mr/strings.xml +++ b/tools/recovery_l10n/res/values-mr/strings.xml @@ -1,9 +1,9 @@ - "सिस्टम अद्यतन स्थापित करीत आहे" + "सिस्टम अपडेट इंस्टॉल करत आहे" "मिटवत आहे" "कोणताही आदेश नाही" "त्रुटी!" - "सुरक्षा अद्यतन स्थापित करीत आहे" + "सुरक्षा अपडेट इंस्टॉल करत आहे" diff --git a/tools/recovery_l10n/res/values-pa/strings.xml b/tools/recovery_l10n/res/values-pa/strings.xml deleted file mode 100644 index 8564c9c36..000000000 --- a/tools/recovery_l10n/res/values-pa/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "ਸਿਸਟਮ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" - "ਮਿਟਾਈ ਜਾ ਰਹੀ ਹੈ" - "ਕੋਈ ਕਮਾਂਡ ਨਹੀਂ" - "ਅਸ਼ੁੱਧੀ!" - "ਸੁਰੱਖਿਆ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" - diff --git a/tools/recovery_l10n/res/values-pt-rBR/strings.xml b/tools/recovery_l10n/res/values-pt-rBR/strings.xml deleted file mode 100644 index b72704385..000000000 --- a/tools/recovery_l10n/res/values-pt-rBR/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Instalando atualização do sistema" - "Apagando" - "Nenhum comando" - "Erro!" - "Instalando atualização de segurança" - diff --git a/tools/recovery_l10n/res/values-sq/strings.xml b/tools/recovery_l10n/res/values-sq/strings.xml deleted file mode 100644 index 1156931fb..000000000 --- a/tools/recovery_l10n/res/values-sq/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Po instalon përditësimin e sistemit" - "Po spastron" - "Nuk ka komanda" - "Gabim!" - "Po instalon përditësimin e sigurisë" - diff --git a/tools/recovery_l10n/res/values-te/strings.xml b/tools/recovery_l10n/res/values-te/strings.xml deleted file mode 100644 index cfb02c915..000000000 --- a/tools/recovery_l10n/res/values-te/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "సిస్టమ్ నవీకరణను ఇన్‍స్టాల్ చేస్తోంది" - "డేటాను తొలగిస్తోంది" - "ఆదేశం లేదు" - "లోపం సంభవించింది!" - "భద్రతా నవీకరణను ఇన్‌స్టాల్ చేస్తోంది" - diff --git a/tools/recovery_l10n/res/values-ur/strings.xml b/tools/recovery_l10n/res/values-ur/strings.xml deleted file mode 100644 index 12e32fbc1..000000000 --- a/tools/recovery_l10n/res/values-ur/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "سسٹم اپ ڈیٹ انسٹال ہو رہی ہے" - "صاف ہو رہا ہے" - "کوئی کمانڈ نہیں ہے" - "خرابی!" - "سیکیورٹی اپ ڈیٹ انسٹال ہو رہی ہے" - diff --git a/tools/recovery_l10n/res/values-uz/strings.xml b/tools/recovery_l10n/res/values-uz/strings.xml deleted file mode 100644 index 2c309d646..000000000 --- a/tools/recovery_l10n/res/values-uz/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - "Tizim yangilanishi o‘rnatilmoqda" - "Tozalanmoqda…" - "Buyruq yo‘q" - "Xato!" - "Xavfsizlik yangilanishi o‘rnatilmoqda" - -- cgit v1.2.3 From e332c5ad0e83c36683f8d1a1d5dd795d17b4aada Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Thu, 17 Aug 2017 00:34:01 -0700 Subject: Import translations. DO NOT MERGE Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import Bug: 64680434 Change-Id: Ie356071f322238a5fb3a4610d2a79141c9aa9377 --- tools/recovery_l10n/res/values-az/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-b+sr+Latn/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-be/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-bs/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-en-rAU/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-en-rCA/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-en-rXC/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-gu/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-kk/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-kn/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-pa/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-pt-rBR/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-sq/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-te/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-ur/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-uz/strings.xml | 9 +++++++++ 16 files changed, 144 insertions(+) create mode 100644 tools/recovery_l10n/res/values-az/strings.xml create mode 100644 tools/recovery_l10n/res/values-b+sr+Latn/strings.xml create mode 100644 tools/recovery_l10n/res/values-be/strings.xml create mode 100644 tools/recovery_l10n/res/values-bs/strings.xml create mode 100644 tools/recovery_l10n/res/values-en-rAU/strings.xml create mode 100644 tools/recovery_l10n/res/values-en-rCA/strings.xml create mode 100644 tools/recovery_l10n/res/values-en-rXC/strings.xml create mode 100644 tools/recovery_l10n/res/values-gu/strings.xml create mode 100644 tools/recovery_l10n/res/values-kk/strings.xml create mode 100644 tools/recovery_l10n/res/values-kn/strings.xml create mode 100644 tools/recovery_l10n/res/values-pa/strings.xml create mode 100644 tools/recovery_l10n/res/values-pt-rBR/strings.xml create mode 100644 tools/recovery_l10n/res/values-sq/strings.xml create mode 100644 tools/recovery_l10n/res/values-te/strings.xml create mode 100644 tools/recovery_l10n/res/values-ur/strings.xml create mode 100644 tools/recovery_l10n/res/values-uz/strings.xml diff --git a/tools/recovery_l10n/res/values-az/strings.xml b/tools/recovery_l10n/res/values-az/strings.xml new file mode 100644 index 000000000..c6765a9ea --- /dev/null +++ b/tools/recovery_l10n/res/values-az/strings.xml @@ -0,0 +1,9 @@ + + + "Sistem güncəlləməsi quraşdırılır..." + "Silinir" + "Əmr yoxdur" + "Xəta!" + "Təhlükəsizlik güncəlləməsi yüklənir" + diff --git a/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml b/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml new file mode 100644 index 000000000..c2d8f2239 --- /dev/null +++ b/tools/recovery_l10n/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,9 @@ + + + "Ažuriranje sistema se instalira" + "Briše se" + "Nema komande" + "Greška!" + "Instalira se bezbednosno ažuriranje" + diff --git a/tools/recovery_l10n/res/values-be/strings.xml b/tools/recovery_l10n/res/values-be/strings.xml new file mode 100644 index 000000000..7c0954d31 --- /dev/null +++ b/tools/recovery_l10n/res/values-be/strings.xml @@ -0,0 +1,9 @@ + + + "Усталёўка абнаўлення сістэмы" + "Сціранне" + "Няма каманды" + "Памылка" + "Усталёўка абнаўлення сістэмы бяспекі" + diff --git a/tools/recovery_l10n/res/values-bs/strings.xml b/tools/recovery_l10n/res/values-bs/strings.xml new file mode 100644 index 000000000..412cf0276 --- /dev/null +++ b/tools/recovery_l10n/res/values-bs/strings.xml @@ -0,0 +1,9 @@ + + + "Ažuriranje sistema…" + "Brisanje u toku" + "Nema komande" + "Greška!" + "Instaliranje sigurnosnog ažuriranja…" + diff --git a/tools/recovery_l10n/res/values-en-rAU/strings.xml b/tools/recovery_l10n/res/values-en-rAU/strings.xml new file mode 100644 index 000000000..dc75c2374 --- /dev/null +++ b/tools/recovery_l10n/res/values-en-rAU/strings.xml @@ -0,0 +1,9 @@ + + + "Installing system update" + "Erasing" + "No command" + "Error!" + "Installing security update" + diff --git a/tools/recovery_l10n/res/values-en-rCA/strings.xml b/tools/recovery_l10n/res/values-en-rCA/strings.xml new file mode 100644 index 000000000..dc75c2374 --- /dev/null +++ b/tools/recovery_l10n/res/values-en-rCA/strings.xml @@ -0,0 +1,9 @@ + + + "Installing system update" + "Erasing" + "No command" + "Error!" + "Installing security update" + diff --git a/tools/recovery_l10n/res/values-en-rXC/strings.xml b/tools/recovery_l10n/res/values-en-rXC/strings.xml new file mode 100644 index 000000000..2d528b3fb --- /dev/null +++ b/tools/recovery_l10n/res/values-en-rXC/strings.xml @@ -0,0 +1,9 @@ + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎Installing system update‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎Erasing‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎No command‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎Error!‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎Installing security update‎‏‎‎‏‎" + diff --git a/tools/recovery_l10n/res/values-gu/strings.xml b/tools/recovery_l10n/res/values-gu/strings.xml new file mode 100644 index 000000000..2355a0f4f --- /dev/null +++ b/tools/recovery_l10n/res/values-gu/strings.xml @@ -0,0 +1,9 @@ + + + "સિસ્ટમ અપડેટ ઇન્સ્ટૉલ કરી રહ્યાં છે" + "કાઢી નાખી રહ્યું છે" + "કોઈ આદેશ નથી" + "ભૂલ!" + "સુરક્ષા અપડેટ ઇન્સ્ટૉલ કરી રહ્યાં છે" + diff --git a/tools/recovery_l10n/res/values-kk/strings.xml b/tools/recovery_l10n/res/values-kk/strings.xml new file mode 100644 index 000000000..a4bd86e66 --- /dev/null +++ b/tools/recovery_l10n/res/values-kk/strings.xml @@ -0,0 +1,9 @@ + + + "Жүйе жаңартуы орнатылуда" + "Өшірілуде" + "Пәрмен жоқ" + "Қате!" + "Қауіпсіздік жаңартуы орнатылуда" + diff --git a/tools/recovery_l10n/res/values-kn/strings.xml b/tools/recovery_l10n/res/values-kn/strings.xml new file mode 100644 index 000000000..5bf6260ee --- /dev/null +++ b/tools/recovery_l10n/res/values-kn/strings.xml @@ -0,0 +1,9 @@ + + + "ಸಿಸ್ಟಂ ಅಪ್‌ಡೇಟ್‌ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ" + "ಅಳಿಸಲಾಗುತ್ತಿದೆ" + "ಯಾವುದೇ ಆದೇಶವಿಲ್ಲ" + "ದೋಷ!" + "ಭದ್ರತೆಯ ಅಪ್‌ಡೇಟ್‌ ಸ್ಥಾಪಿಸಲಾಗುತ್ತಿದೆ" + diff --git a/tools/recovery_l10n/res/values-pa/strings.xml b/tools/recovery_l10n/res/values-pa/strings.xml new file mode 100644 index 000000000..8564c9c36 --- /dev/null +++ b/tools/recovery_l10n/res/values-pa/strings.xml @@ -0,0 +1,9 @@ + + + "ਸਿਸਟਮ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" + "ਮਿਟਾਈ ਜਾ ਰਹੀ ਹੈ" + "ਕੋਈ ਕਮਾਂਡ ਨਹੀਂ" + "ਅਸ਼ੁੱਧੀ!" + "ਸੁਰੱਖਿਆ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" + diff --git a/tools/recovery_l10n/res/values-pt-rBR/strings.xml b/tools/recovery_l10n/res/values-pt-rBR/strings.xml new file mode 100644 index 000000000..b72704385 --- /dev/null +++ b/tools/recovery_l10n/res/values-pt-rBR/strings.xml @@ -0,0 +1,9 @@ + + + "Instalando atualização do sistema" + "Apagando" + "Nenhum comando" + "Erro!" + "Instalando atualização de segurança" + diff --git a/tools/recovery_l10n/res/values-sq/strings.xml b/tools/recovery_l10n/res/values-sq/strings.xml new file mode 100644 index 000000000..1156931fb --- /dev/null +++ b/tools/recovery_l10n/res/values-sq/strings.xml @@ -0,0 +1,9 @@ + + + "Po instalon përditësimin e sistemit" + "Po spastron" + "Nuk ka komanda" + "Gabim!" + "Po instalon përditësimin e sigurisë" + diff --git a/tools/recovery_l10n/res/values-te/strings.xml b/tools/recovery_l10n/res/values-te/strings.xml new file mode 100644 index 000000000..cfb02c915 --- /dev/null +++ b/tools/recovery_l10n/res/values-te/strings.xml @@ -0,0 +1,9 @@ + + + "సిస్టమ్ నవీకరణను ఇన్‍స్టాల్ చేస్తోంది" + "డేటాను తొలగిస్తోంది" + "ఆదేశం లేదు" + "లోపం సంభవించింది!" + "భద్రతా నవీకరణను ఇన్‌స్టాల్ చేస్తోంది" + diff --git a/tools/recovery_l10n/res/values-ur/strings.xml b/tools/recovery_l10n/res/values-ur/strings.xml new file mode 100644 index 000000000..12e32fbc1 --- /dev/null +++ b/tools/recovery_l10n/res/values-ur/strings.xml @@ -0,0 +1,9 @@ + + + "سسٹم اپ ڈیٹ انسٹال ہو رہی ہے" + "صاف ہو رہا ہے" + "کوئی کمانڈ نہیں ہے" + "خرابی!" + "سیکیورٹی اپ ڈیٹ انسٹال ہو رہی ہے" + diff --git a/tools/recovery_l10n/res/values-uz/strings.xml b/tools/recovery_l10n/res/values-uz/strings.xml new file mode 100644 index 000000000..2c309d646 --- /dev/null +++ b/tools/recovery_l10n/res/values-uz/strings.xml @@ -0,0 +1,9 @@ + + + "Tizim yangilanishi o‘rnatilmoqda" + "Tozalanmoqda…" + "Buyruq yo‘q" + "Xato!" + "Xavfsizlik yangilanishi o‘rnatilmoqda" + -- cgit v1.2.3 From 7b795abd13ba11280920c6b39174d2b02b014970 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 23 Aug 2017 19:34:04 -0700 Subject: Import translations. DO NOT MERGE Change-Id: I8fb3f973ecd0dfe54dea048ef445d45902eae028 Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- tools/recovery_l10n/res/values-hi/strings.xml | 2 +- tools/recovery_l10n/res/values-mr/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/recovery_l10n/res/values-hi/strings.xml b/tools/recovery_l10n/res/values-hi/strings.xml index a8a876ee4..65d003352 100644 --- a/tools/recovery_l10n/res/values-hi/strings.xml +++ b/tools/recovery_l10n/res/values-hi/strings.xml @@ -3,7 +3,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "सिस्टम अपडेट इंस्टॉल किया जा रहा है" "मिटाया जा रहा है" - "कोई आदेश नहीं" + "कोई निर्देश नहीं मिला" "गड़बड़ी!" "सुरक्षा अपडेट इंस्टॉल किया जा रहा है" diff --git a/tools/recovery_l10n/res/values-mr/strings.xml b/tools/recovery_l10n/res/values-mr/strings.xml index 017a515c0..a5eff84c7 100644 --- a/tools/recovery_l10n/res/values-mr/strings.xml +++ b/tools/recovery_l10n/res/values-mr/strings.xml @@ -3,7 +3,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "सिस्टम अपडेट इंस्टॉल करत आहे" "मिटवत आहे" - "कोणताही आदेश नाही" + "कोणतीही कमांड नाही" "त्रुटी!" "सुरक्षा अपडेट इंस्टॉल करत आहे" -- cgit v1.2.3 From 9227a5ecec12a4b74c2986b023649f7b1fc24b20 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Sun, 27 Aug 2017 11:10:05 -0700 Subject: Import translations. DO NOT MERGE Change-Id: I0b2ff87788553d2c49519d005f8876cd7318b8c6 Auto-generated-cl: translation import --- tools/recovery_l10n/res/values-mr/strings.xml | 2 +- tools/recovery_l10n/res/values-te/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/recovery_l10n/res/values-mr/strings.xml b/tools/recovery_l10n/res/values-mr/strings.xml index a5eff84c7..5f820336f 100644 --- a/tools/recovery_l10n/res/values-mr/strings.xml +++ b/tools/recovery_l10n/res/values-mr/strings.xml @@ -4,6 +4,6 @@ "सिस्टम अपडेट इंस्टॉल करत आहे" "मिटवत आहे" "कोणतीही कमांड नाही" - "त्रुटी!" + "एरर!" "सुरक्षा अपडेट इंस्टॉल करत आहे" diff --git a/tools/recovery_l10n/res/values-te/strings.xml b/tools/recovery_l10n/res/values-te/strings.xml index cfb02c915..e35c82bc4 100644 --- a/tools/recovery_l10n/res/values-te/strings.xml +++ b/tools/recovery_l10n/res/values-te/strings.xml @@ -4,6 +4,6 @@ "సిస్టమ్ నవీకరణను ఇన్‍స్టాల్ చేస్తోంది" "డేటాను తొలగిస్తోంది" "ఆదేశం లేదు" - "లోపం సంభవించింది!" + "ఎర్రర్ సంభవించింది!" "భద్రతా నవీకరణను ఇన్‌స్టాల్ చేస్తోంది" -- cgit v1.2.3 From 8f84774a68e54f08dd0b5285bd524b56966f3f52 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 6 Sep 2017 06:24:06 -0700 Subject: Import translations. DO NOT MERGE Change-Id: If7aad0299a372403f2875fe3aeb60ad07acb7b47 Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- tools/recovery_l10n/res/values-pa/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/recovery_l10n/res/values-pa/strings.xml b/tools/recovery_l10n/res/values-pa/strings.xml index 8564c9c36..abc771978 100644 --- a/tools/recovery_l10n/res/values-pa/strings.xml +++ b/tools/recovery_l10n/res/values-pa/strings.xml @@ -3,7 +3,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ਸਿਸਟਮ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" "ਮਿਟਾਈ ਜਾ ਰਹੀ ਹੈ" - "ਕੋਈ ਕਮਾਂਡ ਨਹੀਂ" + "ਕੋਈ ਆਦੇਸ਼ ਨਹੀਂ" "ਅਸ਼ੁੱਧੀ!" "ਸੁਰੱਖਿਆ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" -- cgit v1.2.3 From 4d9bd3798e99bf7eaa3628a1b88da4a39b38b06d Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 13 Sep 2017 08:18:22 -0700 Subject: Import translations. DO NOT MERGE Change-Id: I8de15b09695dea1a53a368c942cb8a7dd30ed87d Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- tools/recovery_l10n/res/values-pa/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/recovery_l10n/res/values-pa/strings.xml b/tools/recovery_l10n/res/values-pa/strings.xml index abc771978..27972d117 100644 --- a/tools/recovery_l10n/res/values-pa/strings.xml +++ b/tools/recovery_l10n/res/values-pa/strings.xml @@ -1,9 +1,9 @@ - "ਸਿਸਟਮ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" + "ਸਿਸਟਮ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" "ਮਿਟਾਈ ਜਾ ਰਹੀ ਹੈ" "ਕੋਈ ਆਦੇਸ਼ ਨਹੀਂ" "ਅਸ਼ੁੱਧੀ!" - "ਸੁਰੱਖਿਆ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" + "ਸੁਰੱਖਿਆ ਅੱਪਡੇਟ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" -- cgit v1.2.3 From 559a6d1d2ae2e5145641e1eb16e2c015d756d8c9 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Fri, 27 Oct 2017 23:39:45 -0700 Subject: update_verifier: Fix the wrong computation with group_range_count. 'group_range_count' doesn't properly consider the pair-wise range structure. It may split the ranges into wrong pairs if it evaluates to an odd number. For example, for an input range string of "6,0,2,10,12,20,22" with 4 threads, group_range_count becomes 1. It would then try to verify (0,2), (2,10), (10,12) and (12,20). Note that (2,10) and (12,20) are not valid ranges to be verified, and with (20,22) uncovered. Bug: 68343761 Test: Trigger update_verifier verification. Check the number of verified blocks against the one in care_map.txt. Change-Id: I7c5769325d9866be06c45e7dbcc0c8ea266de714 (cherry picked from commit 62caeb5f48c9d7b1a8ed97c4a021195b8499b804) --- update_verifier/update_verifier.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp index faebbede0..ba7b7aec4 100644 --- a/update_verifier/update_verifier.cpp +++ b/update_verifier/update_verifier.cpp @@ -137,11 +137,12 @@ static bool read_blocks(const std::string& partition, const std::string& range_s LOG(ERROR) << "Error in parsing range string."; return false; } + range_count /= 2; std::vector> threads; size_t thread_num = std::thread::hardware_concurrency() ?: 4; - thread_num = std::min(thread_num, range_count / 2); - size_t group_range_count = range_count / thread_num; + thread_num = std::min(thread_num, range_count); + size_t group_range_count = (range_count + thread_num - 1) / thread_num; for (size_t t = 0; t < thread_num; t++) { auto thread_func = [t, group_range_count, &dm_block_device, &ranges, &partition]() { @@ -154,7 +155,8 @@ static bool read_blocks(const std::string& partition, const std::string& range_s return false; } - for (size_t i = 1 + group_range_count * t; i < group_range_count * (t + 1) + 1; i += 2) { + for (size_t i = group_range_count * 2 * t + 1; + i < std::min(group_range_count * 2 * (t + 1) + 1, ranges.size()); i += 2) { unsigned int range_start, range_end; bool parse_status = android::base::ParseUint(ranges[i], &range_start); parse_status = parse_status && android::base::ParseUint(ranges[i + 1], &range_end); -- cgit v1.2.3 From ddc850adc37de909a2a6fc9c48b9c1e7240f40a7 Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Thu, 2 Nov 2017 11:58:12 -0700 Subject: recovery: remove make_ext4fs from updater Bug: 64395169 Change-Id: I6f6a4f82b225435c6ad5c828e110fa135e6f7579 --- updater/install.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/updater/install.cpp b/updater/install.cpp index 9425d1872..b865081b4 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include @@ -284,14 +283,8 @@ Value* FormatFn(const char* name, State* state, const std::vector(mke2fs_argv)); if (status != 0) { - LOG(WARNING) << name << ": mke2fs failed (" << status << ") on " << location - << ", falling back to make_ext4fs"; - status = make_ext4fs(location.c_str(), size, mount_point.c_str(), sehandle); - if (status != 0) { - LOG(ERROR) << name << ": make_ext4fs failed (" << status << ") on " << location; - return StringValue(""); - } - return StringValue(location); + LOG(ERROR) << name << ": mke2fs failed (" << status << ") on " << location; + return StringValue(""); } const char* e2fsdroid_argv[] = { "/sbin/e2fsdroid_static", "-e", "-a", mount_point.c_str(), -- cgit v1.2.3 From e8e4c40246a8c15208b70b4467a0d1790c7ce8fb Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Wed, 8 Nov 2017 14:56:03 -0800 Subject: is_battery_ok use health 2.0 HAL Test: call is_battery_ok in graphics test, and test manually Bug: 69268160 Bug: 63702641 Change-Id: Ifcf4d2e2cb459689c11fc5d1b880bb053aaae8ae --- Android.mk | 15 +++++++- recovery.cpp | 122 ++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 84 insertions(+), 53 deletions(-) diff --git a/Android.mk b/Android.mk index d9966b7cc..50627b9b9 100644 --- a/Android.mk +++ b/Android.mk @@ -147,10 +147,21 @@ endif LOCAL_C_INCLUDES += \ system/vold \ +# Health HAL dependency LOCAL_STATIC_LIBRARIES := \ + android.hardware.health@2.0-impl \ + android.hardware.health@2.0 \ + android.hardware.health@1.0 \ + android.hardware.health@1.0-convert \ + libhidltransport \ + libhidlbase \ + libhwbinder \ + libvndksupport \ + libbatterymonitor + +LOCAL_STATIC_LIBRARIES += \ librecovery \ libverifier \ - libbatterymonitor \ libbootloader_message \ libfs_mgr \ libext4_utils \ @@ -169,8 +180,8 @@ LOCAL_STATIC_LIBRARIES := \ libvintf \ libtinyxml2 \ libbase \ - libcutils \ libutils \ + libcutils \ liblog \ libselinux \ libz diff --git a/recovery.cpp b/recovery.cpp index a89916337..7574065a4 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -50,9 +50,9 @@ #include #include #include /* for property_list */ -#include -#include /* private pmsg functions */ -#include /* for AID_SYSTEM */ +#include +#include /* for AID_SYSTEM */ +#include /* private pmsg functions */ #include #include #include @@ -1260,56 +1260,76 @@ void UiLogger(android::base::LogId /* id */, android::base::LogSeverity severity } static bool is_battery_ok() { - struct healthd_config healthd_config = { - .batteryStatusPath = android::String8(android::String8::kEmptyString), - .batteryHealthPath = android::String8(android::String8::kEmptyString), - .batteryPresentPath = android::String8(android::String8::kEmptyString), - .batteryCapacityPath = android::String8(android::String8::kEmptyString), - .batteryVoltagePath = android::String8(android::String8::kEmptyString), - .batteryTemperaturePath = android::String8(android::String8::kEmptyString), - .batteryTechnologyPath = android::String8(android::String8::kEmptyString), - .batteryCurrentNowPath = android::String8(android::String8::kEmptyString), - .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString), - .batteryChargeCounterPath = android::String8(android::String8::kEmptyString), - .batteryFullChargePath = android::String8(android::String8::kEmptyString), - .batteryCycleCountPath = android::String8(android::String8::kEmptyString), - .energyCounter = NULL, - .boot_min_cap = 0, - .screen_on = NULL - }; - healthd_board_init(&healthd_config); + using android::hardware::health::V1_0::BatteryStatus; + using android::hardware::health::V2_0::Result; + using android::hardware::health::V2_0::toString; + using android::hardware::health::V2_0::implementation::Health; + + struct healthd_config healthd_config = { + .batteryStatusPath = android::String8(android::String8::kEmptyString), + .batteryHealthPath = android::String8(android::String8::kEmptyString), + .batteryPresentPath = android::String8(android::String8::kEmptyString), + .batteryCapacityPath = android::String8(android::String8::kEmptyString), + .batteryVoltagePath = android::String8(android::String8::kEmptyString), + .batteryTemperaturePath = android::String8(android::String8::kEmptyString), + .batteryTechnologyPath = android::String8(android::String8::kEmptyString), + .batteryCurrentNowPath = android::String8(android::String8::kEmptyString), + .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString), + .batteryChargeCounterPath = android::String8(android::String8::kEmptyString), + .batteryFullChargePath = android::String8(android::String8::kEmptyString), + .batteryCycleCountPath = android::String8(android::String8::kEmptyString), + .energyCounter = NULL, + .boot_min_cap = 0, + .screen_on = NULL + }; - android::BatteryMonitor monitor; - monitor.init(&healthd_config); + auto health = + android::hardware::health::V2_0::implementation::Health::initInstance(&healthd_config); - int wait_second = 0; - while (true) { - int charge_status = monitor.getChargeStatus(); - // Treat unknown status as charged. - bool charged = (charge_status != android::BATTERY_STATUS_DISCHARGING && - charge_status != android::BATTERY_STATUS_NOT_CHARGING); - android::BatteryProperty capacity; - android::status_t status = monitor.getProperty(android::BATTERY_PROP_CAPACITY, &capacity); - ui_print("charge_status %d, charged %d, status %d, capacity %lld\n", charge_status, - charged, status, capacity.valueInt64); - // At startup, the battery drivers in devices like N5X/N6P take some time to load - // the battery profile. Before the load finishes, it reports value 50 as a fake - // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected - // to finish loading the battery profile earlier than 10 seconds after kernel startup. - if (status == 0 && capacity.valueInt64 == 50) { - if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) { - sleep(1); - wait_second++; - continue; - } - } - // If we can't read battery percentage, it may be a device without battery. In this - // situation, use 100 as a fake battery percentage. - if (status != 0) { - capacity.valueInt64 = 100; - } - return (charged && capacity.valueInt64 >= BATTERY_WITH_CHARGER_OK_PERCENTAGE) || - (!charged && capacity.valueInt64 >= BATTERY_OK_PERCENTAGE); + int wait_second = 0; + while (true) { + auto charge_status = BatteryStatus::UNKNOWN; + health + ->getChargeStatus([&charge_status](auto res, auto out_status) { + if (res == Result::SUCCESS) { + charge_status = out_status; + } + }) + .isOk(); // should not have transport error + + // Treat unknown status as charged. + bool charged = (charge_status != BatteryStatus::DISCHARGING && + charge_status != BatteryStatus::NOT_CHARGING); + + Result res = Result::UNKNOWN; + int32_t capacity = INT32_MIN; + health + ->getCapacity([&res, &capacity](auto out_res, auto out_capacity) { + res = out_res; + capacity = out_capacity; + }) + .isOk(); // should not have transport error + + ui_print("charge_status %d, charged %d, status %s, capacity %" PRId32 "\n", charge_status, + charged, toString(res).c_str(), capacity); + // At startup, the battery drivers in devices like N5X/N6P take some time to load + // the battery profile. Before the load finishes, it reports value 50 as a fake + // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected + // to finish loading the battery profile earlier than 10 seconds after kernel startup. + if (res == Result::SUCCESS && capacity == 50) { + if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) { + sleep(1); + wait_second++; + continue; + } + } + // If we can't read battery percentage, it may be a device without battery. In this + // situation, use 100 as a fake battery percentage. + if (res != Result::SUCCESS) { + capacity = 100; + } + return (charged && capacity >= BATTERY_WITH_CHARGER_OK_PERCENTAGE) || + (!charged && capacity >= BATTERY_OK_PERCENTAGE); } } -- cgit v1.2.3 From bd84bd438aa8bee6ed975af962a4d8abe0a5ce57 Mon Sep 17 00:00:00 2001 From: Hridya Valsaraju Date: Wed, 10 Jan 2018 16:18:42 -0800 Subject: Statically link with libhealthstoragedefault This is to add empty implementations of Health HAL methods to report storage info. Bug: 68388678 Test: vts-tradefed run vts -m VtsHalHealthV2_0 Change-Id: I4f093903f485519e16f39384f5c96fcd031438ba --- Android.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/Android.mk b/Android.mk index 54f405466..199cee7ec 100644 --- a/Android.mk +++ b/Android.mk @@ -153,6 +153,7 @@ LOCAL_STATIC_LIBRARIES := \ android.hardware.health@2.0 \ android.hardware.health@1.0 \ android.hardware.health@1.0-convert \ + libhealthstoragedefault \ libhidltransport \ libhidlbase \ libhwbinder \ -- cgit v1.2.3 From 0bfea531d89943595405033288ffca6388a0a113 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 21 Feb 2018 17:03:26 -0800 Subject: Import translations. DO NOT MERGE Change-Id: I60c4e4ebce0bf3abcc2b0b5ab90b0fc5e9406c34 Auto-generated-cl: translation import --- tools/recovery_l10n/res/values-as/strings.xml | 9 +++++++++ tools/recovery_l10n/res/values-or/strings.xml | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 tools/recovery_l10n/res/values-as/strings.xml create mode 100644 tools/recovery_l10n/res/values-or/strings.xml diff --git a/tools/recovery_l10n/res/values-as/strings.xml b/tools/recovery_l10n/res/values-as/strings.xml new file mode 100644 index 000000000..2624cebe4 --- /dev/null +++ b/tools/recovery_l10n/res/values-as/strings.xml @@ -0,0 +1,9 @@ + + + "আপডেইট ইনষ্টল কৰি থকা হৈছে" + "মচি থকা হৈছে" + "কোনো আদেশ নাই" + "ত্ৰুটি!" + "সুৰক্ষা আপডেইট ইনষ্টল কৰি থকা হৈছে" + diff --git a/tools/recovery_l10n/res/values-or/strings.xml b/tools/recovery_l10n/res/values-or/strings.xml new file mode 100644 index 000000000..2b0851cdd --- /dev/null +++ b/tools/recovery_l10n/res/values-or/strings.xml @@ -0,0 +1,9 @@ + + + "ସିଷ୍ଟମ ଅପଡେଟ ଇନଷ୍ଟଲ କରୁଛି" + "ଲିଭାଉଛି" + "କୌଣସି କମାଣ୍ଡ ନାହିଁ" + "ତ୍ରୁଟି!" + "ସୁରକ୍ଷା ଅପ୍‌ଡେଟ୍‌ ଇନ୍‌ଷ୍ଟଲ୍‌ କରୁଛି" + -- cgit v1.2.3 From 01daebbe68943725e7b80e30082330c6bd042a88 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Thu, 8 Mar 2018 12:34:19 -0800 Subject: Set the update locations to default in CacheLocation's constructor Otherwise the applypatch executable will fail to back up the source file to /cache when patching the recovery image. Bug: 74198354 Test: run applypatch from boot to recovery (cherry picked from commit b4e3a370bf6fe2bbb6ad8e33d16ce3210595aaef) Change-Id: I37b7fd88d66ab49ef953d4b7dca22577bd1472e1 --- otautil/cache_location.cpp | 9 ++++----- otautil/include/otautil/cache_location.h | 5 +---- updater/updater.cpp | 4 ---- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/otautil/cache_location.cpp b/otautil/cache_location.cpp index 8f289487f..8ddefec5e 100644 --- a/otautil/cache_location.cpp +++ b/otautil/cache_location.cpp @@ -25,8 +25,7 @@ CacheLocation& CacheLocation::location() { return cache_location; } -void CacheLocation::ResetLocations() { - cache_temp_source_ = kDefaultCacheTempSource; - last_command_file_ = kDefaultLastCommandFile; - stash_directory_base_ = kDefaultStashDirectoryBase; -} +CacheLocation::CacheLocation() + : cache_temp_source_(kDefaultCacheTempSource), + last_command_file_(kDefaultLastCommandFile), + stash_directory_base_(kDefaultStashDirectoryBase) {} diff --git a/otautil/include/otautil/cache_location.h b/otautil/include/otautil/cache_location.h index 85e0d485c..f2f663816 100644 --- a/otautil/include/otautil/cache_location.h +++ b/otautil/include/otautil/cache_location.h @@ -27,9 +27,6 @@ class CacheLocation { public: static CacheLocation& location(); - // Reset the locations to their default values. - void ResetLocations(); - // getter and setter functions. std::string cache_temp_source() const { return cache_temp_source_; @@ -53,7 +50,7 @@ class CacheLocation { } private: - CacheLocation() {} + CacheLocation(); DISALLOW_COPY_AND_ASSIGN(CacheLocation); // When there isn't enough room on the target filesystem to hold the patched version of the file, diff --git a/updater/updater.cpp b/updater/updater.cpp index f063e5fa1..1d6b172bb 100644 --- a/updater/updater.cpp +++ b/updater/updater.cpp @@ -169,10 +169,6 @@ int main(int argc, char** argv) { } ota_io_init(za, state.is_retry); - // Initialize the cache_temp_source, last_command_file and stash_directory_base to their default - // locations. - CacheLocation::location().ResetLocations(); - std::string result; bool status = Evaluate(&state, root, &result); -- cgit v1.2.3 From 91b48f9161a918e4af6233af7fa842b9af0a6bac Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Tue, 6 Mar 2018 17:59:58 -0800 Subject: recovery: add libhidl-gen-utils depedency introduced as a depedency to libvintf. Test: builds Bug: 73556059 Change-Id: Ia51ba81ef462879481dcacb80d9ea9ea35e8b0bb Merged-In: Ia51ba81ef462879481dcacb80d9ea9ea35e8b0bb --- Android.mk | 1 + tests/Android.mk | 1 + 2 files changed, 2 insertions(+) diff --git a/Android.mk b/Android.mk index 199cee7ec..461ad9449 100644 --- a/Android.mk +++ b/Android.mk @@ -179,6 +179,7 @@ LOCAL_STATIC_LIBRARIES += \ libcrypto \ libvintf_recovery \ libvintf \ + libhidl-gen-utils \ libtinyxml2 \ libbase \ libutils \ diff --git a/tests/Android.mk b/tests/Android.mk index d911c25e4..b3584fe87 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -147,6 +147,7 @@ LOCAL_STATIC_LIBRARIES := \ libfs_mgr \ libvintf_recovery \ libvintf \ + libhidl-gen-utils \ libtinyxml2 \ libselinux \ libext4_utils \ -- cgit v1.2.3 From d26f95287a0efc6a3160624fa4e577891a2c9794 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 12 Mar 2018 21:18:52 -0700 Subject: tests: Add ApplyPatchModesTest.PatchModeEmmcTargetWithBsdiffPatch test. /system/bin/applypatch on device is expected to work with bsdiff based recovery-from-boot patch automatically. Adding a test to ensure that's always the case. Bug: 72731506 Test: Run recovery_component_test on marlin. Change-Id: I56283cd3ce7cf0215cc3bb3619b206fa01d552c4 Merged-In: I56283cd3ce7cf0215cc3bb3619b206fa01d552c4 (cherry picked from commit d612b23dfd58dbe5059ba53d8fd13cbb343b177c) --- tests/component/applypatch_test.cpp | 51 +++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp index b6d092557..61e06adb6 100644 --- a/tests/component/applypatch_test.cpp +++ b/tests/component/applypatch_test.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "applypatch/applypatch.h" @@ -38,6 +39,8 @@ #include "otautil/cache_location.h" #include "otautil/print_sha1.h" +using namespace std::string_literals; + static void sha1sum(const std::string& fname, std::string* sha1, size_t* fsize = nullptr) { ASSERT_NE(nullptr, sha1); @@ -265,6 +268,54 @@ TEST_F(ApplyPatchModesTest, PatchModeEmmcTarget) { ASSERT_EQ(0, applypatch_modes(args3.size(), args3.data())); } +// Ensures that applypatch works with a bsdiff based recovery-from-boot.p. +TEST_F(ApplyPatchModesTest, PatchModeEmmcTargetWithBsdiffPatch) { + std::string boot_img_file = from_testdata_base("boot.img"); + std::string boot_img_sha1; + size_t boot_img_size; + sha1sum(boot_img_file, &boot_img_sha1, &boot_img_size); + + std::string recovery_img_file = from_testdata_base("recovery.img"); + std::string recovery_img_sha1; + size_t recovery_img_size; + sha1sum(recovery_img_file, &recovery_img_sha1, &recovery_img_size); + + // Generate the bsdiff patch of recovery-from-boot.p. + std::string src_content; + ASSERT_TRUE(android::base::ReadFileToString(boot_img_file, &src_content)); + + std::string tgt_content; + ASSERT_TRUE(android::base::ReadFileToString(recovery_img_file, &tgt_content)); + + TemporaryFile patch_file; + ASSERT_EQ(0, + bsdiff::bsdiff(reinterpret_cast(src_content.data()), src_content.size(), + reinterpret_cast(tgt_content.data()), tgt_content.size(), + patch_file.path, nullptr)); + + // applypatch : + std::string src_file_arg = + "EMMC:" + boot_img_file + ":" + std::to_string(boot_img_size) + ":" + boot_img_sha1; + TemporaryFile tgt_file; + std::string tgt_file_arg = "EMMC:"s + tgt_file.path; + std::string recovery_img_size_arg = std::to_string(recovery_img_size); + std::string patch_arg = boot_img_sha1 + ":" + patch_file.path; + std::vector args = { "applypatch", + src_file_arg.c_str(), + tgt_file_arg.c_str(), + recovery_img_sha1.c_str(), + recovery_img_size_arg.c_str(), + patch_arg.c_str() }; + ASSERT_EQ(0, applypatch_modes(args.size(), args.data())); + + // Double check the patched recovery image. + std::string tgt_file_sha1; + size_t tgt_file_size; + sha1sum(tgt_file.path, &tgt_file_sha1, &tgt_file_size); + ASSERT_EQ(recovery_img_size, tgt_file_size); + ASSERT_EQ(recovery_img_sha1, tgt_file_sha1); +} + TEST_F(ApplyPatchModesTest, PatchModeInvalidArgs) { // Invalid bonus file. ASSERT_NE(0, applypatch_modes(3, (const char* []){ "applypatch", "-b", "/doesntexist" })); -- cgit v1.2.3 From 454d8cb805e633aaa1c6456a57ec9c2dc6c6e163 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 22 Mar 2018 16:07:00 -0700 Subject: update_verifier: Support verifying product partition. We have added the support for building /product partition in build system (the CL in [1]), where /product is an optional partition that contains system files. This CL adds the matching support if /product needs to be verified during A/B OTA (i.e. listed in care_map file). [1]: commit b7735d81054002961b681f4bdf296d4de2701135, https://android-review.googlesource.com/c/platform/build/+/598454 Bug: 63974895 Test: Run update_verifier test on walleye. Change-Id: Ia1c35e9583b8e66c98a4495b1f81a5ea7e65036f (cherry picked from commit ec2e8c6c1ef3cbafa129ade95abca3203e062b5f) --- tests/component/update_verifier_test.cpp | 3 +-- update_verifier/update_verifier.cpp | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/tests/component/update_verifier_test.cpp b/tests/component/update_verifier_test.cpp index b04e1185e..1544bb2a4 100644 --- a/tests/component/update_verifier_test.cpp +++ b/tests/component/update_verifier_test.cpp @@ -46,7 +46,6 @@ TEST_F(UpdateVerifierTest, verify_image_smoke) { return; } - // The care map file can have only two or four lines. TemporaryFile temp_file; std::string content = "system\n2,0,1"; ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); @@ -58,7 +57,7 @@ TEST_F(UpdateVerifierTest, verify_image_smoke) { } TEST_F(UpdateVerifierTest, verify_image_wrong_lines) { - // The care map file can have only two or four lines. + // The care map file can have only 2 / 4 / 6 lines. TemporaryFile temp_file; ASSERT_FALSE(verify_image(temp_file.path)); diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp index c5e154f03..92d931371 100644 --- a/update_verifier/update_verifier.cpp +++ b/update_verifier/update_verifier.cpp @@ -74,14 +74,13 @@ static int dm_name_filter(const dirent* de) { } static bool read_blocks(const std::string& partition, const std::string& range_str) { - if (partition != "system" && partition != "vendor") { - LOG(ERROR) << "partition name must be system or vendor: " << partition; + if (partition != "system" && partition != "vendor" && partition != "product") { + LOG(ERROR) << "Invalid partition name \"" << partition << "\""; return false; } - // Iterate the content of "/sys/block/dm-X/dm/name". If it matches "system" - // (or "vendor"), then dm-X is a dm-wrapped system/vendor partition. - // Afterwards, update_verifier will read every block on the care_map_file of - // "/dev/block/dm-X" to ensure the partition's integrity. + // Iterate the content of "/sys/block/dm-X/dm/name". If it matches one of "system", "vendor" or + // "product", then dm-X is a dm-wrapped device for that target. We will later read all the + // ("cared") blocks from "/dev/block/dm-X" to ensure the target partition's integrity. static constexpr auto DM_PATH_PREFIX = "/sys/block/"; dirent** namelist; int n = scandir(DM_PATH_PREFIX, &namelist, dm_name_filter, alphasort); @@ -206,10 +205,9 @@ bool verify_image(const std::string& care_map_name) { PLOG(WARNING) << "Failed to open " << care_map_name; return true; } - // Care map file has four lines (two lines if vendor partition is not present): - // First line has the block partition name (system/vendor). - // Second line holds all ranges of blocks to verify. - // The next two lines have the same format but for vendor partition. + // care_map file has up to six lines, where every two lines make a pair. Within each pair, the + // first line has the partition name (e.g. "system"), while the second line holds the ranges of + // all the blocks to verify. std::string file_content; if (!android::base::ReadFdToString(care_map_fd.get(), &file_content)) { LOG(ERROR) << "Error reading care map contents to string."; @@ -218,9 +216,9 @@ bool verify_image(const std::string& care_map_name) { std::vector lines; lines = android::base::Split(android::base::Trim(file_content), "\n"); - if (lines.size() != 2 && lines.size() != 4) { + if (lines.size() != 2 && lines.size() != 4 && lines.size() != 6) { LOG(ERROR) << "Invalid lines in care_map: found " << lines.size() - << " lines, expecting 2 or 4 lines."; + << " lines, expecting 2 or 4 or 6 lines."; return false; } -- cgit v1.2.3 From ba0460c981d8178859d4987f3554401545228a71 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Tue, 20 Mar 2018 16:07:39 -0700 Subject: Factor out a menu class for screen ui Also consolidate the duplicate codes to draw the menu in ScreenRecoveryUI and WearRecoveryUI. This helps us to support text icons as menu in the future. Bug: 74397117 Test: Check the menu under recovery on bullhead and a wear device. Change-Id: Iba9b646c3828670f0e78a7e07d1a94a44e96bb0b (cherry picked from commit 2b3f80068ece1040ba7c923afe1e70b705535ad5) --- Android.mk | 77 +++++++++------- screen_ui.cpp | 183 +++++++++++++++++++++++++++++--------- screen_ui.h | 73 +++++++++++++++- tests/Android.mk | 4 +- tests/unit/screen_ui_test.cpp | 198 ++++++++++++++++++++++++++++++++++++++++++ wear_ui.cpp | 116 ++----------------------- wear_ui.h | 4 - 7 files changed, 471 insertions(+), 184 deletions(-) create mode 100644 tests/unit/screen_ui_test.cpp diff --git a/Android.mk b/Android.mk index 56d69c03b..0499a6da8 100644 --- a/Android.mk +++ b/Android.mk @@ -53,36 +53,21 @@ LOCAL_STATIC_LIBRARIES := \ include $(BUILD_STATIC_LIBRARY) -# recovery (static executable) +# librecovery_ui (static library) # =============================== include $(CLEAR_VARS) - LOCAL_SRC_FILES := \ - adb_install.cpp \ - device.cpp \ - fuse_sdcard_provider.cpp \ - recovery.cpp \ - roots.cpp \ - rotate_logs.cpp \ screen_ui.cpp \ ui.cpp \ vr_ui.cpp \ - wear_ui.cpp \ + wear_ui.cpp -LOCAL_MODULE := recovery - -LOCAL_FORCE_STATIC_EXECUTABLE := true - -LOCAL_REQUIRED_MODULES := e2fsdroid_static mke2fs_static mke2fs.conf - -ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) -ifeq ($(HOST_OS),linux) -LOCAL_REQUIRED_MODULES += sload.f2fs mkfs.f2fs -endif -endif +LOCAL_CFLAGS := -Wall -Werror -LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) -LOCAL_CFLAGS += -Wall -Werror +LOCAL_MODULE := librecovery_ui +LOCAL_STATIC_LIBRARIES := \ + libminui \ + libbase ifneq ($(TARGET_RECOVERY_UI_MARGIN_HEIGHT),) LOCAL_CFLAGS += -DRECOVERY_UI_MARGIN_HEIGHT=$(TARGET_RECOVERY_UI_MARGIN_HEIGHT) @@ -132,6 +117,36 @@ else LOCAL_CFLAGS += -DRECOVERY_UI_VR_STEREO_OFFSET=0 endif +include $(BUILD_STATIC_LIBRARY) + +# recovery (static executable) +# =============================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + adb_install.cpp \ + device.cpp \ + fuse_sdcard_provider.cpp \ + recovery.cpp \ + roots.cpp \ + rotate_logs.cpp \ + + +LOCAL_MODULE := recovery + +LOCAL_FORCE_STATIC_EXECUTABLE := true + +LOCAL_REQUIRED_MODULES := e2fsdroid_static mke2fs_static mke2fs.conf + +ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) +ifeq ($(HOST_OS),linux) +LOCAL_REQUIRED_MODULES += sload.f2fs mkfs.f2fs +endif +endif + +LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) +LOCAL_CFLAGS += -Wall -Werror + LOCAL_C_INCLUDES += \ system/vold \ @@ -148,8 +163,17 @@ LOCAL_STATIC_LIBRARIES := \ libvndksupport \ libbatterymonitor +LOCAL_STATIC_LIBRARIES += librecovery + +# If $(TARGET_RECOVERY_UI_LIB) is defined, the recovery calls make_device() from the +# $(TARGET_RECOVERY_UI_LIB), which depends on the librecovery_ui. +ifeq ($(TARGET_RECOVERY_UI_LIB),) + LOCAL_SRC_FILES += default_device.cpp +else + LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB) +endif + LOCAL_STATIC_LIBRARIES += \ - librecovery \ libverifier \ libbootloader_message \ libfs_mgr \ @@ -161,6 +185,7 @@ LOCAL_STATIC_LIBRARIES += \ libminadbd \ libasyncio \ libfusesideload \ + librecovery_ui \ libminui \ libpng \ libcrypto_utils \ @@ -184,12 +209,6 @@ endif LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin -ifeq ($(TARGET_RECOVERY_UI_LIB),) - LOCAL_SRC_FILES += default_device.cpp -else - LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB) -endif - ifeq ($(BOARD_CACHEIMAGE_PARTITION_SIZE),) LOCAL_REQUIRED_MODULES += recovery-persist recovery-refresh endif diff --git a/screen_ui.cpp b/screen_ui.cpp index c8fb5aa75..317e5529c 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -53,7 +53,98 @@ static double now() { return tv.tv_sec + tv.tv_usec / 1000000.0; } -ScreenRecoveryUI::ScreenRecoveryUI() +Menu::Menu(bool scrollable, size_t max_items, size_t max_length) + : scrollable_(scrollable), + max_display_items_(max_items), + max_item_length_(max_length), + text_headers_(nullptr), + menu_start_(0), + selection_(0) { + CHECK_LE(max_items, static_cast(std::numeric_limits::max())); +} + +const char* const* Menu::text_headers() const { + return text_headers_; +} + +std::string Menu::TextItem(size_t index) const { + CHECK_LT(index, text_items_.size()); + + return text_items_[index]; +} + +size_t Menu::MenuStart() const { + return menu_start_; +} + +size_t Menu::MenuEnd() const { + return std::min(ItemsCount(), menu_start_ + max_display_items_); +} + +size_t Menu::ItemsCount() const { + return text_items_.size(); +} + +bool Menu::ItemsOverflow(std::string* cur_selection_str) const { + if (!scrollable_ || static_cast(ItemsCount()) <= max_display_items_) { + return false; + } + + *cur_selection_str = + android::base::StringPrintf("Current item: %d/%zu", selection_ + 1, ItemsCount()); + return true; +} + +void Menu::Start(const char* const* headers, const char* const* items, int initial_selection) { + text_headers_ = headers; + + // It's fine to have more entries than text_rows_ if scrollable menu is supported. + size_t max_items_count = scrollable_ ? std::numeric_limits::max() : max_display_items_; + for (size_t i = 0; i < max_items_count && items[i] != nullptr; ++i) { + text_items_.emplace_back(items[i], strnlen(items[i], max_item_length_)); + } + + CHECK(!text_items_.empty()); + selection_ = initial_selection; +} + +// TODO(xunchang) modify the function parameters to button up & down. +int Menu::Select(int sel) { + CHECK_LE(ItemsCount(), static_cast(std::numeric_limits::max())); + int count = ItemsCount(); + + // Wraps the selection at boundary if the menu is not scrollable. + if (!scrollable_) { + if (sel < 0) { + selection_ = count - 1; + } else if (sel >= count) { + selection_ = 0; + } else { + selection_ = sel; + } + + return selection_; + } + + if (sel < 0) { + selection_ = 0; + } else if (sel >= count) { + selection_ = count - 1; + } else { + if (static_cast(sel) < menu_start_) { + menu_start_--; + } else if (static_cast(sel) >= MenuEnd()) { + menu_start_++; + } + selection_ = sel; + } + + return selection_; +} + +ScreenRecoveryUI::ScreenRecoveryUI() : ScreenRecoveryUI(false) {} + +ScreenRecoveryUI::ScreenRecoveryUI(bool scrollable_menu) : kMarginWidth(RECOVERY_UI_MARGIN_WIDTH), kMarginHeight(RECOVERY_UI_MARGIN_HEIGHT), kAnimationFps(RECOVERY_UI_ANIMATION_FPS), @@ -71,10 +162,7 @@ ScreenRecoveryUI::ScreenRecoveryUI() text_row_(0), show_text(false), show_text_ever(false), - menu_headers_(nullptr), - show_menu(false), - menu_items(0), - menu_sel(0), + scrollable_menu_(scrollable_menu), file_viewer_text_(nullptr), intro_frames(0), loop_frames(0), @@ -407,13 +495,13 @@ int ScreenRecoveryUI::DrawWrappedTextLines(int x, int y, const char* const* line static const char* REGULAR_HELP[] = { "Use volume up/down and power.", - NULL + nullptr, }; static const char* LONG_PRESS_HELP[] = { "Any button cycles highlight.", "Long-press activates.", - NULL + nullptr, }; // Redraws everything on the screen. Does not flip pages. Should only be called with updateMutex @@ -428,8 +516,13 @@ void ScreenRecoveryUI::draw_screen_locked() { gr_color(0, 0, 0, 255); gr_clear(); + draw_menu_and_text_buffer_locked(HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP); +} + +// Draws the menu and text buffer on the screen. Should only be called with updateMutex locked. +void ScreenRecoveryUI::draw_menu_and_text_buffer_locked(const char* const* help_message) { int y = kMarginHeight; - if (show_menu) { + if (menu_) { static constexpr int kMenuIndent = 4; int x = kMarginWidth + kMenuIndent; @@ -440,26 +533,46 @@ void ScreenRecoveryUI::draw_screen_locked() { for (const auto& chunk : android::base::Split(recovery_fingerprint, ":")) { y += DrawTextLine(x, y, chunk.c_str(), false); } - y += DrawTextLines(x, y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP); + y += DrawTextLines(x, y, help_message); + + // Draw menu header. SetColor(HEADER); - // Ignore kMenuIndent, which is not taken into account by text_cols_. - y += DrawWrappedTextLines(kMarginWidth, y, menu_headers_); + if (!menu_->scrollable()) { + y += DrawWrappedTextLines(x, y, menu_->text_headers()); + } else { + y += DrawTextLines(x, y, menu_->text_headers()); + // Show the current menu item number in relation to total number if items don't fit on the + // screen. + std::string cur_selection_str; + if (menu_->ItemsOverflow(&cur_selection_str)) { + y += DrawTextLine(x, y, cur_selection_str.c_str(), true); + } + } + // Draw menu items. SetColor(MENU); - y += DrawHorizontalRule(y) + 4; - for (int i = 0; i < menu_items; ++i) { - if (i == menu_sel) { + // Do not draw the horizontal rule for wear devices. + if (!menu_->scrollable()) { + y += DrawHorizontalRule(y) + 4; + } + for (size_t i = menu_->MenuStart(); i < menu_->MenuEnd(); ++i) { + bool bold = false; + if (i == static_cast(menu_->selection())) { // Draw the highlight bar. SetColor(IsLongPress() ? MENU_SEL_BG_ACTIVE : MENU_SEL_BG); - DrawHighlightBar(0, y - 2, ScreenWidth(), char_height_ + 4); + + int bar_height = char_height_ + 4; + DrawHighlightBar(0, y - 2, ScreenWidth(), bar_height); + // Bold white text for the selected item. SetColor(MENU_SEL_FG); - y += DrawTextLine(x, y, menu_[i].c_str(), true); - SetColor(MENU); - } else { - y += DrawTextLine(x, y, menu_[i].c_str(), false); + bold = true; } + + y += DrawTextLine(x, y, menu_->TextItem(i).c_str(), bold); + + SetColor(MENU); } y += DrawHorizontalRule(y); } @@ -864,15 +977,10 @@ void ScreenRecoveryUI::ShowFile(const char* filename) { void ScreenRecoveryUI::StartMenu(const char* const* headers, const char* const* items, int initial_selection) { pthread_mutex_lock(&updateMutex); - if (text_rows_ > 0 && text_cols_ > 0) { - menu_headers_ = headers; - menu_.clear(); - for (size_t i = 0; i < text_rows_ && items[i] != nullptr; ++i) { - menu_.emplace_back(std::string(items[i], strnlen(items[i], text_cols_ - 1))); - } - menu_items = static_cast(menu_.size()); - show_menu = true; - menu_sel = initial_selection; + if (text_rows_ > 0 && text_cols_ > 1) { + menu_ = std::make_unique(scrollable_menu_, text_rows_, text_cols_ - 1); + menu_->Start(headers, items, initial_selection); + update_screen_locked(); } pthread_mutex_unlock(&updateMutex); @@ -880,16 +988,13 @@ void ScreenRecoveryUI::StartMenu(const char* const* headers, const char* const* int ScreenRecoveryUI::SelectMenu(int sel) { pthread_mutex_lock(&updateMutex); - if (show_menu) { - int old_sel = menu_sel; - menu_sel = sel; - - // Wrap at top and bottom. - if (menu_sel < 0) menu_sel = menu_items - 1; - if (menu_sel >= menu_items) menu_sel = 0; + if (menu_) { + int old_sel = menu_->selection(); + sel = menu_->Select(sel); - sel = menu_sel; - if (menu_sel != old_sel) update_screen_locked(); + if (sel != old_sel) { + update_screen_locked(); + } } pthread_mutex_unlock(&updateMutex); return sel; @@ -897,8 +1002,8 @@ int ScreenRecoveryUI::SelectMenu(int sel) { void ScreenRecoveryUI::EndMenu() { pthread_mutex_lock(&updateMutex); - if (show_menu && text_rows_ > 0 && text_cols_ > 0) { - show_menu = false; + if (menu_) { + menu_.reset(); update_screen_locked(); } pthread_mutex_unlock(&updateMutex); diff --git a/screen_ui.h b/screen_ui.h index f05761c42..c1222a576 100644 --- a/screen_ui.h +++ b/screen_ui.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -28,6 +29,70 @@ // From minui/minui.h. struct GRSurface; +// This class maintains the menu selection and display of the screen ui. +class Menu { + public: + Menu(bool scrollable, size_t max_items, size_t max_length); + + bool scrollable() const { + return scrollable_; + } + + int selection() const { + return selection_; + } + + // Returns count of menu items. + size_t ItemsCount() const; + // Returns the index of the first menu item. + size_t MenuStart() const; + // Returns the index of the last menu item + 1. + size_t MenuEnd() const; + + // Menu example: + // info: Android Recovery + // .... + // help messages: Swipe up/down to move + // Swipe left/right to select + // empty line (horizontal rule): + // menu headers: Select file to view + // menu items: /cache/recovery/last_log + // /cache/recovery/last_log.1 + // /cache/recovery/last_log.2 + // ... + const char* const* text_headers() const; + std::string TextItem(size_t index) const; + + // Checks if the menu items fit vertically on the screen. Returns true and set the + // |cur_selection_str| if the items exceed the screen limit. + bool ItemsOverflow(std::string* cur_selection_str) const; + + // Starts the menu with |headers| and |items| in text. Sets the default selection to + // |initial_selection|. + void Start(const char* const* headers, const char* const* items, int initial_selection); + + // Sets the current selection to |sel|. Handle the overflow cases depending on if the menu is + // scrollable. + int Select(int sel); + + private: + // The menu is scrollable to display more items. Used on wear devices who have smaller screens. + const bool scrollable_; + // The max number of menu items to fit vertically on a screen. + const size_t max_display_items_; + // The length of each item to fit horizontally on a screen. + const size_t max_item_length_; + + // Internal storage for the menu headers and items in text. + const char* const* text_headers_; + std::vector text_items_; + + // The first item to display on the screen. + size_t menu_start_; + // Current menu selection. + int selection_; +}; + // Implementation of RecoveryUI appropriate for devices with a screen // (shows an icon + a progress bar, text logging, menu, etc.) class ScreenRecoveryUI : public RecoveryUI { @@ -44,6 +109,7 @@ class ScreenRecoveryUI : public RecoveryUI { }; ScreenRecoveryUI(); + explicit ScreenRecoveryUI(bool scrollable_menu); bool Init(const std::string& locale) override; @@ -101,6 +167,7 @@ class ScreenRecoveryUI : public RecoveryUI { virtual void draw_background_locked(); virtual void draw_foreground_locked(); virtual void draw_screen_locked(); + virtual void draw_menu_and_text_buffer_locked(const char* const* help_message); virtual void update_screen_locked(); virtual void update_progress_locked(); @@ -184,10 +251,8 @@ class ScreenRecoveryUI : public RecoveryUI { bool show_text; bool show_text_ever; // has show_text ever been true? - std::vector menu_; - const char* const* menu_headers_; - bool show_menu; - int menu_items, menu_sel; + bool scrollable_menu_; + std::unique_ptr menu_; // An alternate text screen, swapped with 'text_' when we're viewing a log file. char** file_viewer_text_; diff --git a/tests/Android.mk b/tests/Android.mk index b3584fe87..9a71371fa 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -23,6 +23,7 @@ LOCAL_MODULE := recovery_unit_test LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_STATIC_LIBRARIES := \ libverifier \ + librecovery_ui \ libminui \ libotautil \ libupdater \ @@ -38,8 +39,9 @@ LOCAL_SRC_FILES := \ unit/dirutil_test.cpp \ unit/locale_test.cpp \ unit/rangeset_test.cpp \ + unit/screen_ui_test.cpp \ unit/sysutil_test.cpp \ - unit/zip_test.cpp \ + unit/zip_test.cpp LOCAL_C_INCLUDES := bootable/recovery LOCAL_SHARED_LIBRARIES := liblog diff --git a/tests/unit/screen_ui_test.cpp b/tests/unit/screen_ui_test.cpp new file mode 100644 index 000000000..be6799f2e --- /dev/null +++ b/tests/unit/screen_ui_test.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2018 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 "screen_ui.h" + +#include + +#include + +constexpr const char* HEADER[] = { "header", nullptr }; +constexpr const char* ITEMS[] = { "items1", "items2", "items3", "items4", "1234567890", nullptr }; + +TEST(ScreenUITest, StartPhoneMenuSmoke) { + Menu menu(false, 10, 20); + ASSERT_FALSE(menu.scrollable()); + + menu.Start(HEADER, ITEMS, 0); + ASSERT_EQ(HEADER[0], menu.text_headers()[0]); + ASSERT_EQ(5u, menu.ItemsCount()); + + std::string message; + ASSERT_FALSE(menu.ItemsOverflow(&message)); + for (size_t i = 0; i < menu.ItemsCount(); i++) { + ASSERT_EQ(ITEMS[i], menu.TextItem(i)); + } + + ASSERT_EQ(0, menu.selection()); +} + +TEST(ScreenUITest, StartWearMenuSmoke) { + Menu menu(true, 10, 8); + ASSERT_TRUE(menu.scrollable()); + + menu.Start(HEADER, ITEMS, 1); + ASSERT_EQ(HEADER[0], menu.text_headers()[0]); + ASSERT_EQ(5u, menu.ItemsCount()); + + std::string message; + ASSERT_FALSE(menu.ItemsOverflow(&message)); + for (size_t i = 0; i < menu.ItemsCount() - 1; i++) { + ASSERT_EQ(ITEMS[i], menu.TextItem(i)); + } + // Test of the last item is truncated + ASSERT_EQ("12345678", menu.TextItem(4)); + ASSERT_EQ(1, menu.selection()); +} + +TEST(ScreenUITest, StartPhoneMenuItemsOverflow) { + Menu menu(false, 1, 20); + ASSERT_FALSE(menu.scrollable()); + + menu.Start(HEADER, ITEMS, 0); + ASSERT_EQ(1u, menu.ItemsCount()); + + std::string message; + ASSERT_FALSE(menu.ItemsOverflow(&message)); + for (size_t i = 0; i < menu.ItemsCount(); i++) { + ASSERT_EQ(ITEMS[i], menu.TextItem(i)); + } + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(1u, menu.MenuEnd()); +} + +TEST(ScreenUITest, StartWearMenuItemsOverflow) { + Menu menu(true, 1, 20); + ASSERT_TRUE(menu.scrollable()); + + menu.Start(HEADER, ITEMS, 0); + ASSERT_EQ(5u, menu.ItemsCount()); + + std::string message; + ASSERT_TRUE(menu.ItemsOverflow(&message)); + ASSERT_EQ("Current item: 1/5", message); + + for (size_t i = 0; i < menu.ItemsCount(); i++) { + ASSERT_EQ(ITEMS[i], menu.TextItem(i)); + } + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(1u, menu.MenuEnd()); +} + +TEST(ScreenUITest, PhoneMenuSelectSmoke) { + Menu menu(false, 10, 20); + + int sel = 0; + menu.Start(HEADER, ITEMS, sel); + // Mimic down button 10 times (2 * items size) + for (int i = 0; i < 10; i++) { + sel = menu.Select(++sel); + ASSERT_EQ(sel, menu.selection()); + + // Wraps the selection for unscrollable menu when it reaches the boundary. + int expected = (i + 1) % 5; + ASSERT_EQ(expected, menu.selection()); + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + } + + // Mimic up button 10 times + for (int i = 0; i < 10; i++) { + sel = menu.Select(--sel); + ASSERT_EQ(sel, menu.selection()); + + int expected = (9 - i) % 5; + ASSERT_EQ(expected, menu.selection()); + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + } +} + +TEST(ScreenUITest, WearMenuSelectSmoke) { + Menu menu(true, 10, 20); + + int sel = 0; + menu.Start(HEADER, ITEMS, sel); + // Mimic pressing down button 10 times (2 * items size) + for (int i = 0; i < 10; i++) { + sel = menu.Select(++sel); + ASSERT_EQ(sel, menu.selection()); + + // Stops the selection at the boundary if the menu is scrollable. + int expected = std::min(i + 1, 4); + ASSERT_EQ(expected, menu.selection()); + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + } + + // Mimic pressing up button 10 times + for (int i = 0; i < 10; i++) { + sel = menu.Select(--sel); + ASSERT_EQ(sel, menu.selection()); + + int expected = std::max(3 - i, 0); + ASSERT_EQ(expected, menu.selection()); + + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + } +} + +TEST(ScreenUITest, WearMenuSelectItemsOverflow) { + Menu menu(true, 3, 20); + + int sel = 1; + menu.Start(HEADER, ITEMS, sel); + ASSERT_EQ(5u, menu.ItemsCount()); + + // Scroll the menu to the end, and check the start & end of menu. + for (int i = 0; i < 3; i++) { + sel = menu.Select(++sel); + ASSERT_EQ(i + 2, sel); + ASSERT_EQ(static_cast(i), menu.MenuStart()); + ASSERT_EQ(static_cast(i + 3), menu.MenuEnd()); + } + + // Press down button one more time won't change the MenuStart() and MenuEnd(). + sel = menu.Select(++sel); + ASSERT_EQ(4, sel); + ASSERT_EQ(2u, menu.MenuStart()); + ASSERT_EQ(5u, menu.MenuEnd()); + + // Scroll the menu to the top. + // The expected menu sel, start & ends are: + // sel 3, start 2, end 5 + // sel 2, start 2, end 5 + // sel 1, start 1, end 4 + // sel 0, start 0, end 3 + for (int i = 0; i < 4; i++) { + sel = menu.Select(--sel); + ASSERT_EQ(3 - i, sel); + ASSERT_EQ(static_cast(std::min(3 - i, 2)), menu.MenuStart()); + ASSERT_EQ(static_cast(std::min(6 - i, 5)), menu.MenuEnd()); + } + + // Press up button one more time won't change the MenuStart() and MenuEnd(). + sel = menu.Select(--sel); + ASSERT_EQ(0, sel); + ASSERT_EQ(0u, menu.MenuStart()); + ASSERT_EQ(3u, menu.MenuEnd()); +} diff --git a/wear_ui.cpp b/wear_ui.cpp index ca6b1b102..118e43508 100644 --- a/wear_ui.cpp +++ b/wear_ui.cpp @@ -17,7 +17,6 @@ #include "wear_ui.h" #include -#include // TODO: Remove after killing the call to sprintf(). #include #include @@ -27,7 +26,8 @@ #include WearRecoveryUI::WearRecoveryUI() - : kProgressBarBaseline(RECOVERY_UI_PROGRESS_BAR_BASELINE), + : ScreenRecoveryUI(true), + kProgressBarBaseline(RECOVERY_UI_PROGRESS_BAR_BASELINE), kMenuUnusableRows(RECOVERY_UI_MENU_UNUSABLE_ROWS) { // TODO: kMenuUnusableRows should be computed based on the lines in draw_screen_locked(). @@ -65,13 +65,10 @@ static const char* SWIPE_HELP[] = { "Swipe up/down to move.", "Swipe left/right to select.", "", - NULL + nullptr, }; -// TODO merge drawing routines with screen_ui void WearRecoveryUI::draw_screen_locked() { - char cur_selection_str[50]; - draw_background_locked(); if (!show_text) { draw_foreground_locked(); @@ -79,68 +76,7 @@ void WearRecoveryUI::draw_screen_locked() { SetColor(TEXT_FILL); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); - int y = kMarginHeight; - int x = kMarginWidth; - if (show_menu) { - std::string recovery_fingerprint = - android::base::GetProperty("ro.bootimage.build.fingerprint", ""); - SetColor(HEADER); - y += DrawTextLine(x + 4, y, "Android Recovery", true); - for (auto& chunk : android::base::Split(recovery_fingerprint, ":")) { - y += DrawTextLine(x + 4, y, chunk.c_str(), false); - } - - // This is actually the help strings. - y += DrawTextLines(x + 4, y, SWIPE_HELP); - SetColor(HEADER); - y += DrawTextLines(x + 4, y, menu_headers_); - - // Show the current menu item number in relation to total number if - // items don't fit on the screen. - if (menu_items > menu_end - menu_start) { - sprintf(cur_selection_str, "Current item: %d/%d", menu_sel + 1, menu_items); - gr_text(gr_sys_font(), x + 4, y, cur_selection_str, 1); - y += char_height_ + 4; - } - - // Menu begins here - SetColor(MENU); - - for (int i = menu_start; i < menu_end; ++i) { - 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); - // white text of selected item - SetColor(MENU_SEL_FG); - if (menu_[i][0]) { - gr_text(gr_sys_font(), x + 4, y, menu_[i].c_str(), 1); - } - SetColor(MENU); - } else if (menu_[i][0]) { - gr_text(gr_sys_font(), x + 4, y, menu_[i].c_str(), 0); - } - y += char_height_ + 4; - } - SetColor(MENU); - y += 4; - gr_fill(0, y, gr_fb_width(), y + 2); - y += 4; - } - - SetColor(LOG); - - // display from the bottom up, until we hit the top of the - // screen, the bottom of the menu, or we've displayed the - // entire text buffer. - int row = text_row_; - size_t count = 0; - for (int ty = gr_fb_height() - char_height_ - kMarginHeight; ty > y + 2 && count < text_rows_; - ty -= char_height_, ++count) { - gr_text(gr_sys_font(), x + 4, ty, text_[row], 0); - --row; - if (row < 0) row = text_rows_ - 1; - } + draw_menu_and_text_buffer_locked(SWIPE_HELP); } } @@ -156,45 +92,11 @@ void WearRecoveryUI::StartMenu(const char* const* headers, const char* const* it int initial_selection) { pthread_mutex_lock(&updateMutex); if (text_rows_ > 0 && text_cols_ > 0) { - menu_headers_ = headers; - menu_.clear(); - // "i < text_rows_" is removed from the loop termination condition, - // which is different from the one in ScreenRecoveryUI::StartMenu(). - // Because WearRecoveryUI supports scrollable menu, it's fine to have - // more entries than text_rows_. The menu may be truncated otherwise. - // Bug: 23752519 - for (size_t i = 0; items[i] != nullptr; i++) { - menu_.emplace_back(std::string(items[i], strnlen(items[i], text_cols_ - 1))); - } - menu_items = static_cast(menu_.size()); - show_menu = true; - menu_sel = initial_selection; - menu_start = 0; - menu_end = text_rows_ - 1 - kMenuUnusableRows; - if (menu_items <= menu_end) menu_end = menu_items; - update_screen_locked(); - } - pthread_mutex_unlock(&updateMutex); -} + menu_ = std::make_unique(scrollable_menu_, text_rows_ - kMenuUnusableRows - 1, + text_cols_ - 1); + menu_->Start(headers, items, initial_selection); -int WearRecoveryUI::SelectMenu(int sel) { - int old_sel; - pthread_mutex_lock(&updateMutex); - if (show_menu) { - old_sel = menu_sel; - menu_sel = sel; - if (menu_sel < 0) menu_sel = 0; - if (menu_sel >= menu_items) menu_sel = menu_items - 1; - if (menu_sel < menu_start) { - menu_start--; - menu_end--; - } else if (menu_sel >= menu_end && menu_sel < menu_items) { - menu_end++; - menu_start++; - } - sel = menu_sel; - if (menu_sel != old_sel) update_screen_locked(); + update_screen_locked(); } pthread_mutex_unlock(&updateMutex); - return sel; -} +} \ No newline at end of file diff --git a/wear_ui.h b/wear_ui.h index 739b4cb1d..8b24cb73e 100644 --- a/wear_ui.h +++ b/wear_ui.h @@ -25,10 +25,8 @@ class WearRecoveryUI : public ScreenRecoveryUI { void SetStage(int current, int max) override; - // menu display void StartMenu(const char* const* headers, const char* const* items, int initial_selection) override; - int SelectMenu(int sel) override; protected: // progress bar vertical position, it's centered horizontally @@ -45,8 +43,6 @@ class WearRecoveryUI : public ScreenRecoveryUI { private: void draw_background_locked() override; void draw_screen_locked() override; - - int menu_start, menu_end; }; #endif // RECOVERY_WEAR_UI_H -- cgit v1.2.3 From f7e8012be3c2ac4460b577157e377cd695d411ef Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Fri, 23 Mar 2018 22:01:43 -0700 Subject: Specify a default module for TARGET_RECOVERY_UI_LIB. This aligns the logic between {default,wear,vr}_device.cpp. They all implement their default make_device() functions, but using different RecoveryUI variants. This CL creates a new module librecovery_ui_default that uses ScreenRecoveryUI, which serves as the default value for TARGET_RECOVERY_UI_LIB. Test: lunch aosp_{angler,marlin,dragon,walleye}-userdebug; `mmma -j bootable/recovery` respectively. Change-Id: I6755b09d96e4809bb1c17142895fe1cad95e5a02 (cherry picked from commit 73fd036be8c7563423be0c3adbd4205c4f1bc2f5) --- Android.mk | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Android.mk b/Android.mk index 0499a6da8..7359c9fbd 100644 --- a/Android.mk +++ b/Android.mk @@ -18,6 +18,11 @@ LOCAL_PATH := $(call my-dir) RECOVERY_API_VERSION := 3 RECOVERY_FSTAB_VERSION := 2 +# TARGET_RECOVERY_UI_LIB should be one of librecovery_ui_{default,wear,vr} or a device-specific +# module that defines make_device() and the exact RecoveryUI class for the target. It defaults to +# librecovery_ui_default, which uses ScreenRecoveryUI. +TARGET_RECOVERY_UI_LIB ?= librecovery_ui_default + # libmounts (static library) # =============================== include $(CLEAR_VARS) @@ -32,8 +37,10 @@ include $(BUILD_STATIC_LIBRARY) # librecovery (static library) # =============================== include $(CLEAR_VARS) + LOCAL_SRC_FILES := \ install.cpp + LOCAL_CFLAGS := -Wall -Werror LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION) @@ -131,7 +138,6 @@ LOCAL_SRC_FILES := \ roots.cpp \ rotate_logs.cpp \ - LOCAL_MODULE := recovery LOCAL_FORCE_STATIC_EXECUTABLE := true @@ -163,17 +169,9 @@ LOCAL_STATIC_LIBRARIES := \ libvndksupport \ libbatterymonitor -LOCAL_STATIC_LIBRARIES += librecovery - -# If $(TARGET_RECOVERY_UI_LIB) is defined, the recovery calls make_device() from the -# $(TARGET_RECOVERY_UI_LIB), which depends on the librecovery_ui. -ifeq ($(TARGET_RECOVERY_UI_LIB),) - LOCAL_SRC_FILES += default_device.cpp -else - LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB) -endif - LOCAL_STATIC_LIBRARIES += \ + librecovery \ + $(TARGET_RECOVERY_UI_LIB) \ libverifier \ libbootloader_message \ libfs_mgr \ @@ -254,6 +252,16 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_CFLAGS := -Wall -Werror include $(BUILD_STATIC_LIBRARY) +# Generic device that uses ScreenRecoveryUI. +# =============================== +include $(CLEAR_VARS) +LOCAL_SRC_FILES := default_device.cpp +LOCAL_CFLAGS := -Wall -Werror + +LOCAL_MODULE := librecovery_ui_default + +include $(BUILD_STATIC_LIBRARY) + # Wear default device # =============================== include $(CLEAR_VARS) -- cgit v1.2.3 From 10b3faa10db9ea1af66f2ae8ecdf9225f882f7f6 Mon Sep 17 00:00:00 2001 From: Yi Kong Date: Tue, 3 Apr 2018 12:45:45 -0700 Subject: Use non-LTO variant of libhwbinder ... as a workaround for build system does not currently infer non-LTO usage from Android.mk. Test: m Bug: 77320844 Change-Id: I6e9954b895051cc20408a30d0761e164e4c5bfd9 --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index 461ad9449..4f7ced268 100644 --- a/Android.mk +++ b/Android.mk @@ -156,7 +156,7 @@ LOCAL_STATIC_LIBRARIES := \ libhealthstoragedefault \ libhidltransport \ libhidlbase \ - libhwbinder \ + libhwbinder_nolto \ libvndksupport \ libbatterymonitor -- cgit v1.2.3 From 4358262b757a39fe7939369be4afa6869e8caa3a Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Mon, 2 Apr 2018 13:37:35 -0700 Subject: mkfs.f2fs: specify sector size for target image size The total sectors that we want to format is used in different meanings from various users. This notifies its size based on 4096 bytes explicitly. Bug: 76407663 Change-Id: I3392646648264ad1ca78e4b87240edc9385a0cc4 Merged-In: I3392646648264ad1ca78e4b87240edc9385a0cc4 Reported-by: katao@xiaomi.com Signed-off-by: Jaegeuk Kim --- roots.cpp | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/roots.cpp b/roots.cpp index 9ff5186c1..8907bbd9b 100644 --- a/roots.cpp +++ b/roots.cpp @@ -324,19 +324,34 @@ int format_volume(const char* volume, const char* directory) { } // Has to be f2fs because we checked earlier. + static constexpr int kSectorSize = 4096; std::string cmd("/sbin/mkfs.f2fs"); - std::vector make_f2fs_cmd = { cmd, "-d1", "-f", "-O", - "encrypt", "-O", "quota", v->blk_device }; - if (length >= 512) { - make_f2fs_cmd.push_back(std::to_string(length / 512)); + // clang-format off + std::vector make_f2fs_cmd = { + cmd, + "-d1", + "-f", + "-O", "encrypt", + "-O", "quota", + "-w", std::to_string(kSectorSize), + v->blk_device, + }; + // clang-format on + if (length >= kSectorSize) { + make_f2fs_cmd.push_back(std::to_string(length / kSectorSize)); } int result = exec_cmd(make_f2fs_cmd); if (result == 0 && directory != nullptr) { cmd = "/sbin/sload.f2fs"; + // clang-format off std::vector sload_f2fs_cmd = { - cmd, "-f", directory, "-t", volume, v->blk_device, + cmd, + "-f", directory, + "-t", volume, + v->blk_device, }; + // clang-format on result = exec_cmd(sload_f2fs_cmd); } if (result != 0) { -- cgit v1.2.3 From 848f227eea524a48208bdd4181f90fb63a31ed2b Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Fri, 8 Dec 2017 13:19:23 -0800 Subject: f2fs: support f2fs by setting unmovable bit for package file This enables to use uncrypt for f2fs update-on-reboot. It requires kernel patch named: "f2fs: add an ioctl to disable GC for specific file" If any operation fails during uncrypt, please delete package file as soon as possible, and create the file again to move forward. IOWs, don't leave the package file for a long time. Bug: 70309376 Bug: 30170612 Change-Id: I3b4233e7da756f107be35364521699deaf2e7139 Merged-In: I3b4233e7da756f107be35364521699deaf2e7139 Signed-off-by: Jaegeuk Kim --- uncrypt/uncrypt.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index 645faadbf..bb43c2c4a 100644 --- a/uncrypt/uncrypt.cpp +++ b/uncrypt/uncrypt.cpp @@ -172,10 +172,14 @@ static struct fstab* read_fstab() { return fstab; } -static const char* find_block_device(const char* path, bool* encryptable, bool* encrypted) { +static const char* find_block_device(const char* path, bool* encryptable, bool* encrypted, bool *f2fs_fs) { // Look for a volume whose mount point is the prefix of path and // return its block device. Set encrypted if it's currently // encrypted. + + // ensure f2fs_fs is set to 0 first. + if (f2fs_fs) + *f2fs_fs = false; for (int i = 0; i < fstab->num_entries; ++i) { struct fstab_rec* v = &fstab->recs[i]; if (!v->mount_point) { @@ -192,6 +196,8 @@ static const char* find_block_device(const char* path, bool* encryptable, bool* *encrypted = true; } } + if (f2fs_fs && strcmp(v->fs_type, "f2fs") == 0) + *f2fs_fs = true; return v->blk_device; } } @@ -244,7 +250,7 @@ static int retry_fibmap(const int fd, const char* name, int* block, const int he } static int produce_block_map(const char* path, const char* map_file, const char* blk_dev, - bool encrypted, int socket) { + bool encrypted, bool f2fs_fs, int socket) { std::string err; if (!android::base::RemoveFileIfExists(map_file, &err)) { LOG(ERROR) << "failed to remove the existing map file " << map_file << ": " << err; @@ -307,6 +313,17 @@ static int produce_block_map(const char* path, const char* map_file, const char* } } +#ifndef F2FS_IOC_SET_DONTMOVE +#ifndef F2FS_IOCTL_MAGIC +#define F2FS_IOCTL_MAGIC 0xf5 +#endif +#define F2FS_IOC_SET_DONTMOVE _IO(F2FS_IOCTL_MAGIC, 13) +#endif + if (f2fs_fs && ioctl(fd, F2FS_IOC_SET_DONTMOVE) < 0) { + PLOG(ERROR) << "Failed to set non-movable file for f2fs: " << path << " on " << blk_dev; + return kUncryptIoctlError; + } + off64_t pos = 0; int last_progress = 0; while (pos < sb.st_size) { @@ -458,7 +475,8 @@ static int uncrypt(const char* input_path, const char* map_file, const int socke bool encryptable; bool encrypted; - const char* blk_dev = find_block_device(path, &encryptable, &encrypted); + bool f2fs_fs; + const char* blk_dev = find_block_device(path, &encryptable, &encrypted, &f2fs_fs); if (blk_dev == nullptr) { LOG(ERROR) << "failed to find block device for " << path; return kUncryptBlockDeviceFindError; @@ -479,7 +497,7 @@ static int uncrypt(const char* input_path, const char* map_file, const int socke // and /sdcard we leave the file alone. if (strncmp(path, "/data/", 6) == 0) { LOG(INFO) << "writing block map " << map_file; - return produce_block_map(path, map_file, blk_dev, encrypted, socket); + return produce_block_map(path, map_file, blk_dev, encrypted, f2fs_fs, socket); } return 0; -- cgit v1.2.3 From 1224544806382ca98bbb7d9edba83b0c2e1be21f Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 4 Apr 2018 21:14:01 -0700 Subject: install: mkfs.f2fs: specify sector size for target image size The total sectors that we want to format is used in different meanings from various users. This notifies its size based on 512 bytes explicitly. Bug: 76407663 Change-Id: I20687b40a1733d3b459a45f8b64a338c37a7bc95 Signed-off-by: Jaegeuk Kim --- updater/install.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/updater/install.cpp b/updater/install.cpp index 2b6c20fe3..6732ab897 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -548,6 +548,8 @@ Value* FormatFn(const char* name, State* state, const std::vector Date: Thu, 5 Apr 2018 22:42:13 -0700 Subject: recovery: enable fsverity feature bit Bug: 74604441 Bug 67380979 Change-Id: Iab1cc9aef356f0ddf6e2491578a2bd53009182ce Signed-off-by: Jaegeuk Kim --- roots.cpp | 1 + updater/install.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/roots.cpp b/roots.cpp index 8907bbd9b..184e7992b 100644 --- a/roots.cpp +++ b/roots.cpp @@ -333,6 +333,7 @@ int format_volume(const char* volume, const char* directory) { "-f", "-O", "encrypt", "-O", "quota", + "-O", "verity", "-w", std::to_string(kSectorSize), v->blk_device, }; diff --git a/updater/install.cpp b/updater/install.cpp index 6732ab897..9be7645f3 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -544,12 +544,10 @@ Value* FormatFn(const char* name, State* state, const std::vector Date: Mon, 9 Apr 2018 10:38:24 -0700 Subject: Use the non-LTO, non-PGO version of libhwbinder Bug: http://b/77320844 Android.mk doesn't have support for PGO either. This causes linker error (about missing __llvm_profile symbols) in the PGO-instrumentation enabled builds in the release branch. Test: m ANDROID_PGO_INSTRUMENT=ALL Change-Id: Ib5dfdea88073bd95da2cd02e92c85bfffcca80d6 --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index 4f7ced268..7e0ad122e 100644 --- a/Android.mk +++ b/Android.mk @@ -156,7 +156,7 @@ LOCAL_STATIC_LIBRARIES := \ libhealthstoragedefault \ libhidltransport \ libhidlbase \ - libhwbinder_nolto \ + libhwbinder_noltopgo \ libvndksupport \ libbatterymonitor -- cgit v1.2.3 From 84c82a8142517f30040bf16bed045eb3b309e967 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Fri, 13 Apr 2018 16:08:01 -0700 Subject: minadbd: track signature change of service_to_fd. Bug: http://b/37066218 Bug: http://b/71898863 Test: treehugger Change-Id: I5f2b14c65cff8d41dd3230d78b87e3e27e489bf6 (cherry picked from commit 570b08b7904901162ae2d4c847b19c1aa9738aaf) --- minadbd/minadbd_services.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp index 9f0f1f87d..043c51a6a 100644 --- a/minadbd/minadbd_services.cpp +++ b/minadbd/minadbd_services.cpp @@ -58,7 +58,7 @@ static int create_service_thread(void (*func)(int, const std::string&), const st return s[0]; } -int service_to_fd(const char* name, const atransport* /* transport */) { +int service_to_fd(const char* name, atransport* /* transport */) { int ret = -1; if (!strncmp(name, "sideload:", 9)) { -- cgit v1.2.3 From 723056a83f8c8b15af02d9c302862dbb2304ea8c Mon Sep 17 00:00:00 2001 From: Paul Crowley Date: Wed, 8 Jun 2016 13:51:41 -0700 Subject: Wipe the metadata partition when we wipe data. Bug: 78469201 Test: Wipe from recovery menu, check that wipe is logged correctly and boot works as expected. Merged-In: I5bc8ef1b83d78de8b5edba6cc17882edcc744356 Change-Id: I5bc8ef1b83d78de8b5edba6cc17882edcc744356 --- recovery.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/recovery.cpp b/recovery.cpp index d887d07fb..07ec5cfb6 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -108,6 +108,7 @@ 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* METADATA_ROOT = "/metadata"; static const char *SDCARD_ROOT = "/sdcard"; static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log"; static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install"; @@ -752,11 +753,19 @@ static bool wipe_data(Device* device) { modified_flash = true; ui->Print("\n-- Wiping data...\n"); - bool success = - device->PreWipeData() && - erase_volume("/data") && - (has_cache ? erase_volume("/cache") : true) && - device->PostWipeData(); + bool success = device->PreWipeData(); + if (success) { + success &= erase_volume(DATA_ROOT); + if (has_cache) { + success &= erase_volume(CACHE_ROOT); + } + if (volume_for_mount_point(METADATA_ROOT) != nullptr) { + success &= erase_volume(METADATA_ROOT); + } + } + if (success) { + success &= device->PostWipeData(); + } ui->Print("Data wipe %s.\n", success ? "complete" : "failed"); return success; } -- cgit v1.2.3 From 370d6008778436de2f59100d122ff4635ba22c91 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 26 Apr 2018 10:24:03 -0700 Subject: Mark ui_print with __printflike. And fix an issue as a result of the change. Test: mmma -j bootable/recovery Change-Id: I94e6384a1f39e9c37a8ed029d235142738d6e5d3 (cherry picked from commit 8af89c3a02c1bf358fc3c3b4e0a7cedc8f48631e) --- common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.h b/common.h index a85130698..4228e71de 100644 --- a/common.h +++ b/common.h @@ -40,7 +40,7 @@ extern const char* reason; // fopen a file, mounting volumes and making parent dirs as necessary. FILE* fopen_path(const std::string& path, const char* mode); -void ui_print(const char* format, ...); +void ui_print(const char* format, ...) __printflike(1, 2); bool is_ro_debuggable(); -- cgit v1.2.3 From 6d90a9d4a0d3dec68e87727e8488ba942a49246f Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Thu, 26 Apr 2018 10:40:36 -0700 Subject: recovery: Print the actually required battery level. It should be one of BATTERY_OK_PERCENTAGE (20) and BATTERY_WITH_CHARGER_OK_PERCENTAGE (15), depending on the charger state. Also move the battery level related constants next to their users. Test: mmma -j bootable/recovery Test: Build and boot into recovery with a pending OTA. Check the log. Change-Id: I7513f59c4718ec8e2db16c5266928470c2308648 (cherry picked from commit f2ea6d79992c4004e693c942e5aa0eb32eb5387d) --- recovery.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/recovery.cpp b/recovery.cpp index 2d81cd629..5a78faeac 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -116,12 +116,6 @@ static const char *LAST_LOG_FILE = "/cache/recovery/last_log"; // We will try to apply the update package 5 times at most in case of an I/O error or // bspatch | imgpatch error. static const int RETRY_LIMIT = 4; -static const int BATTERY_READ_TIMEOUT_IN_SEC = 10; -// GmsCore enters recovery mode to install package when having enough battery -// percentage. Normally, the threshold is 40% without charger and 20% with charger. -// So we should check battery with a slightly lower limitation. -static const int BATTERY_OK_PERCENTAGE = 20; -static const int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15; static constexpr const char* RECOVERY_WIPE = "/etc/recovery.wipe"; static constexpr const char* DEFAULT_LOCALE = "en-US"; @@ -1265,7 +1259,7 @@ void UiLogger(android::base::LogId /* id */, android::base::LogSeverity severity } } -static bool is_battery_ok() { +static bool is_battery_ok(int* required_battery_level) { using android::hardware::health::V1_0::BatteryStatus; using android::hardware::health::V2_0::Result; using android::hardware::health::V2_0::toString; @@ -1284,14 +1278,15 @@ static bool is_battery_ok() { .batteryChargeCounterPath = android::String8(android::String8::kEmptyString), .batteryFullChargePath = android::String8(android::String8::kEmptyString), .batteryCycleCountPath = android::String8(android::String8::kEmptyString), - .energyCounter = NULL, + .energyCounter = nullptr, .boot_min_cap = 0, - .screen_on = NULL + .screen_on = nullptr }; auto health = android::hardware::health::V2_0::implementation::Health::initInstance(&healthd_config); + static constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10; int wait_second = 0; while (true) { auto charge_status = BatteryStatus::UNKNOWN; @@ -1334,9 +1329,15 @@ static bool is_battery_ok() { if (res != Result::SUCCESS) { capacity = 100; } - return (charged && capacity >= BATTERY_WITH_CHARGER_OK_PERCENTAGE) || - (!charged && capacity >= BATTERY_OK_PERCENTAGE); - } + + // GmsCore enters recovery mode to install package when having enough battery percentage. + // Normally, the threshold is 40% without charger and 20% with charger. So we should check + // battery with a slightly lower limitation. + static constexpr int BATTERY_OK_PERCENTAGE = 20; + static constexpr int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15; + *required_battery_level = charged ? BATTERY_WITH_CHARGER_OK_PERCENTAGE : BATTERY_OK_PERCENTAGE; + return capacity >= *required_battery_level; + } } // Set the retry count to |retry_count| in BCB. @@ -1564,9 +1565,10 @@ int main(int argc, char **argv) { // to log the update attempt since update_package is non-NULL. modified_flash = true; - if (retry_count == 0 && !is_battery_ok()) { - ui->Print("battery capacity is not enough for installing package, needed is %d%%\n", - BATTERY_OK_PERCENTAGE); + int required_battery_level; + if (retry_count == 0 && !is_battery_ok(&required_battery_level)) { + ui->Print("battery capacity is not enough for installing package: %d%% needed\n", + required_battery_level); // Log the error code to last_install when installation skips due to // low battery. log_failure_code(kLowBattery, update_package); -- cgit v1.2.3 From 2ac56afc7b3df1989f164b18d24295422a020788 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 25 Apr 2018 16:47:04 -0700 Subject: recovery: Split main() into recovery_main.cpp. This prepares for moving more codes from recovery into librecovery, so that they will become more easily testable. recovery_main.cpp will be the source code for recovery module, with the rest moved into librecovery. recovery_main.cpp mainly does the initializations, such as setting up the logger. Test: mmma -j bootable/recovery Test: recovery_component_test Test: Build and boot into recovery image on marlin. Change-Id: I8e846524546b6f3f0e32ed869e851f62261eef23 (cherry picked from commit c241cb662440551eb0d2f42345f7ee08cf60a7dd) --- Android.mk | 1 + common.h | 6 +- private/recovery.h | 19 +++++++ recovery.cpp | 137 ++------------------------------------------ recovery_main.cpp | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 191 insertions(+), 134 deletions(-) create mode 100644 private/recovery.h create mode 100644 recovery_main.cpp diff --git a/Android.mk b/Android.mk index 5b71bd3da..57b180355 100644 --- a/Android.mk +++ b/Android.mk @@ -126,6 +126,7 @@ LOCAL_SRC_FILES := \ device.cpp \ fuse_sdcard_provider.cpp \ recovery.cpp \ + recovery_main.cpp \ roots.cpp \ rotate_logs.cpp \ diff --git a/common.h b/common.h index 4228e71de..33c5ba08f 100644 --- a/common.h +++ b/common.h @@ -37,9 +37,13 @@ extern std::string stage; // The reason argument provided in "--reason=". extern const char* reason; -// fopen a file, mounting volumes and making parent dirs as necessary. +// fopen(3)'s the given file, by mounting volumes and making parent dirs as necessary. Returns the +// file pointer, or nullptr on error. FILE* fopen_path(const std::string& path, const char* mode); +// In turn fflush(3)'s, fsync(3)'s and fclose(3)'s the given stream. +void check_and_fclose(FILE* fp, const std::string& name); + void ui_print(const char* format, ...) __printflike(1, 2); bool is_ro_debuggable(); diff --git a/private/recovery.h b/private/recovery.h new file mode 100644 index 000000000..5b2ca4b3f --- /dev/null +++ b/private/recovery.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2018 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. + */ + +#pragma once + +int start_recovery(int argc, char** argv); diff --git a/recovery.cpp b/recovery.cpp index 5fc3b1ad8..35d9debe1 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "private/recovery.h" + #include #include #include @@ -35,7 +37,6 @@ #include #include -#include #include #include #include @@ -64,7 +65,6 @@ #include "fuse_sdcard_provider.h" #include "fuse_sideload.h" #include "install.h" -#include "minadbd/minadbd.h" #include "minui/minui.h" #include "otautil/DirUtil.h" #include "otautil/error_code.h" @@ -147,7 +147,6 @@ struct selabel_handle* sehandle; * 7b. the user reboots (pulling the battery, etc) into the main system */ -// Open a given path, mounting partitions as necessary. FILE* fopen_path(const std::string& path, const char* mode) { if (ensure_path_mounted(path.c_str()) != 0) { LOG(ERROR) << "Can't mount " << path; @@ -162,8 +161,7 @@ FILE* fopen_path(const std::string& path, const char* mode) { return fopen(path.c_str(), mode); } -// close a file, log an error if the error indicator is set -static void check_and_fclose(FILE* fp, const std::string& name) { +void check_and_fclose(FILE* fp, const std::string& name) { fflush(fp); if (fsync(fileno(fp)) == -1) { PLOG(ERROR) << "Failed to fsync " << name; @@ -186,92 +184,6 @@ bool reboot(const std::string& command) { return android::base::SetProperty(ANDROID_RB_PROPERTY, cmd); } -static void redirect_stdio(const char* filename) { - int pipefd[2]; - if (pipe(pipefd) == -1) { - PLOG(ERROR) << "pipe failed"; - - // Fall back to traditional logging mode without timestamps. - // If these fail, there's not really anywhere to complain... - freopen(filename, "a", stdout); setbuf(stdout, NULL); - freopen(filename, "a", stderr); setbuf(stderr, NULL); - - return; - } - - pid_t pid = fork(); - if (pid == -1) { - PLOG(ERROR) << "fork failed"; - - // Fall back to traditional logging mode without timestamps. - // If these fail, there's not really anywhere to complain... - freopen(filename, "a", stdout); setbuf(stdout, NULL); - freopen(filename, "a", stderr); setbuf(stderr, NULL); - - return; - } - - if (pid == 0) { - /// Close the unused write end. - close(pipefd[1]); - - auto start = std::chrono::steady_clock::now(); - - // Child logger to actually write to the log file. - FILE* log_fp = fopen(filename, "ae"); - if (log_fp == nullptr) { - PLOG(ERROR) << "fopen \"" << filename << "\" failed"; - close(pipefd[0]); - _exit(EXIT_FAILURE); - } - - FILE* pipe_fp = fdopen(pipefd[0], "r"); - if (pipe_fp == nullptr) { - PLOG(ERROR) << "fdopen failed"; - check_and_fclose(log_fp, filename); - close(pipefd[0]); - _exit(EXIT_FAILURE); - } - - char* line = nullptr; - size_t len = 0; - while (getline(&line, &len, pipe_fp) != -1) { - auto now = std::chrono::steady_clock::now(); - double duration = std::chrono::duration_cast>( - now - start).count(); - if (line[0] == '\n') { - fprintf(log_fp, "[%12.6lf]\n", duration); - } else { - fprintf(log_fp, "[%12.6lf] %s", duration, line); - } - fflush(log_fp); - } - - PLOG(ERROR) << "getline failed"; - - free(line); - check_and_fclose(log_fp, filename); - close(pipefd[0]); - _exit(EXIT_FAILURE); - } else { - // Redirect stdout/stderr to the logger process. - // Close the unused read end. - close(pipefd[0]); - - setbuf(stdout, nullptr); - setbuf(stderr, nullptr); - - if (dup2(pipefd[1], STDOUT_FILENO) == -1) { - PLOG(ERROR) << "dup2 stdout failed"; - } - if (dup2(pipefd[1], STDERR_FILENO) == -1) { - PLOG(ERROR) << "dup2 stderr failed"; - } - - close(pipefd[1]); - } -} - // command line args come from, in decreasing precedence: // - the actual command line // - the bootloader control block (one per line, after "recovery") @@ -1218,18 +1130,6 @@ void ui_print(const char* format, ...) { } } -static constexpr char log_characters[] = "VDIWEF"; - -void UiLogger(android::base::LogId /* id */, android::base::LogSeverity severity, - const char* /* tag */, const char* /* file */, unsigned int /* line */, - const char* message) { - if (severity >= android::base::ERROR && ui != nullptr) { - ui->Print("E:%s\n", message); - } else { - fprintf(stdout, "%c:%s\n", log_characters[severity], message); - } -} - static bool is_battery_ok(int* required_battery_level) { using android::hardware::health::V1_0::BatteryStatus; using android::hardware::health::V2_0::Result; @@ -1359,38 +1259,9 @@ static void log_failure_code(ErrorCode code, const std::string& update_package) LOG(INFO) << log_content; } -int main(int argc, char **argv) { - // We don't have logcat yet under recovery; so we'll print error on screen and - // log to stdout (which is redirected to recovery.log) as we used to do. - android::base::InitLogging(argv, &UiLogger); - - // Take last pmsg contents and rewrite it to the current pmsg session. - static const char filter[] = "recovery/"; - // Do we need to rotate? - bool doRotate = false; - - __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logbasename, &doRotate); - // Take action to refresh pmsg contents - __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logrotate, &doRotate); - - // If this binary is started with the single argument "--adbd", - // instead of being the normal recovery binary, it turns into kind - // of a stripped-down version of adbd that only supports the - // 'sideload' command. Note this must be a real argument, not - // anything in the command file or bootloader control block; the - // only way recovery should be run with this argument is when it - // starts a copy of itself from the apply_from_adb() function. - if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { - minadbd_main(); - return 0; - } - +int start_recovery(int argc, char** argv) { time_t start = time(nullptr); - // redirect_stdio should be called only in non-sideload mode. Otherwise - // we may have two logger instances with different timestamps. - redirect_stdio(Paths::Get().temporary_log_file().c_str()); - printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start)); load_volume_table(); diff --git a/recovery_main.cpp b/recovery_main.cpp new file mode 100644 index 000000000..9f579f7cd --- /dev/null +++ b/recovery_main.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2018 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 +#include +#include + +#include + +#include +#include /* private pmsg functions */ + +#include "common.h" +#include "minadbd/minadbd.h" +#include "otautil/paths.h" +#include "private/recovery.h" +#include "rotate_logs.h" +#include "ui.h" + +static void UiLogger(android::base::LogId /* id */, android::base::LogSeverity severity, + const char* /* tag */, const char* /* file */, unsigned int /* line */, + const char* message) { + static constexpr char log_characters[] = "VDIWEF"; + if (severity >= android::base::ERROR && ui != nullptr) { + ui->Print("E:%s\n", message); + } else { + fprintf(stdout, "%c:%s\n", log_characters[severity], message); + } +} + +static void redirect_stdio(const char* filename) { + int pipefd[2]; + if (pipe(pipefd) == -1) { + PLOG(ERROR) << "pipe failed"; + + // Fall back to traditional logging mode without timestamps. If these fail, there's not really + // anywhere to complain... + freopen(filename, "a", stdout); + setbuf(stdout, nullptr); + freopen(filename, "a", stderr); + setbuf(stderr, nullptr); + + return; + } + + pid_t pid = fork(); + if (pid == -1) { + PLOG(ERROR) << "fork failed"; + + // Fall back to traditional logging mode without timestamps. If these fail, there's not really + // anywhere to complain... + freopen(filename, "a", stdout); + setbuf(stdout, nullptr); + freopen(filename, "a", stderr); + setbuf(stderr, nullptr); + + return; + } + + if (pid == 0) { + /// Close the unused write end. + close(pipefd[1]); + + auto start = std::chrono::steady_clock::now(); + + // Child logger to actually write to the log file. + FILE* log_fp = fopen(filename, "ae"); + if (log_fp == nullptr) { + PLOG(ERROR) << "fopen \"" << filename << "\" failed"; + close(pipefd[0]); + _exit(EXIT_FAILURE); + } + + FILE* pipe_fp = fdopen(pipefd[0], "r"); + if (pipe_fp == nullptr) { + PLOG(ERROR) << "fdopen failed"; + check_and_fclose(log_fp, filename); + close(pipefd[0]); + _exit(EXIT_FAILURE); + } + + char* line = nullptr; + size_t len = 0; + while (getline(&line, &len, pipe_fp) != -1) { + auto now = std::chrono::steady_clock::now(); + double duration = + std::chrono::duration_cast>(now - start).count(); + if (line[0] == '\n') { + fprintf(log_fp, "[%12.6lf]\n", duration); + } else { + fprintf(log_fp, "[%12.6lf] %s", duration, line); + } + fflush(log_fp); + } + + PLOG(ERROR) << "getline failed"; + + free(line); + check_and_fclose(log_fp, filename); + close(pipefd[0]); + _exit(EXIT_FAILURE); + } else { + // Redirect stdout/stderr to the logger process. Close the unused read end. + close(pipefd[0]); + + setbuf(stdout, nullptr); + setbuf(stderr, nullptr); + + if (dup2(pipefd[1], STDOUT_FILENO) == -1) { + PLOG(ERROR) << "dup2 stdout failed"; + } + if (dup2(pipefd[1], STDERR_FILENO) == -1) { + PLOG(ERROR) << "dup2 stderr failed"; + } + + close(pipefd[1]); + } +} + +int main(int argc, char** argv) { + // We don't have logcat yet under recovery; so we'll print error on screen and log to stdout + // (which is redirected to recovery.log) as we used to do. + android::base::InitLogging(argv, &UiLogger); + + // Take last pmsg contents and rewrite it to the current pmsg session. + static constexpr const char filter[] = "recovery/"; + // Do we need to rotate? + bool do_rotate = false; + + __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logbasename, &do_rotate); + // Take action to refresh pmsg contents + __android_log_pmsg_file_read(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filter, logrotate, &do_rotate); + + // If this binary is started with the single argument "--adbd", instead of being the normal + // recovery binary, it turns into kind of a stripped-down version of adbd that only supports the + // 'sideload' command. Note this must be a real argument, not anything in the command file or + // bootloader control block; the only way recovery should be run with this argument is when it + // starts a copy of itself from the apply_from_adb() function. + if (argc == 2 && strcmp(argv[1], "--adbd") == 0) { + minadbd_main(); + return 0; + } + + // redirect_stdio should be called only in non-sideload mode. Otherwise we may have two logger + // instances with different timestamps. + redirect_stdio(Paths::Get().temporary_log_file().c_str()); + + return start_recovery(argc, argv); +} -- cgit v1.2.3 From cadf4ed45137fbb776584b4427694eb783183d7e Mon Sep 17 00:00:00 2001 From: Jerry Zhang Date: Wed, 2 May 2018 16:56:00 -0700 Subject: recovery: Refactor logging code into logging.cpp Move common logging related functions to rotate_logs.cpp, and rename that to logging.cpp. Test: Recovery works Bug: 78793464 Change-Id: I00f20a79a296680122b8437d54a87897c5cb2fc7 (cherry picked from commit 3c3f211d1e5698da6eea9e83584acb2dee4ca46e) --- Android.bp | 12 ++- Android.mk | 2 +- common.h | 9 +- logging.cpp | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++ logging.h | 50 +++++++++++ recovery-persist.cpp | 2 +- recovery-refresh.cpp | 2 +- recovery.cpp | 134 ++-------------------------- recovery_main.cpp | 2 +- rotate_logs.cpp | 107 ----------------------- rotate_logs.h | 38 -------- 11 files changed, 315 insertions(+), 286 deletions(-) create mode 100644 logging.cpp create mode 100644 logging.h delete mode 100644 rotate_logs.cpp delete mode 100644 rotate_logs.h diff --git a/Android.bp b/Android.bp index 9ad961d5b..22c90bd3e 100644 --- a/Android.bp +++ b/Android.bp @@ -89,8 +89,8 @@ cc_binary { ], srcs: [ + "logging.cpp", "recovery-persist.cpp", - "rotate_logs.cpp", ], shared_libs: [ @@ -98,6 +98,10 @@ cc_binary { "liblog", ], + static_libs: [ + "libotautil", + ], + init_rc: [ "recovery-persist.rc", ], @@ -112,8 +116,8 @@ cc_binary { ], srcs: [ + "logging.cpp", "recovery-refresh.cpp", - "rotate_logs.cpp", ], shared_libs: [ @@ -121,6 +125,10 @@ cc_binary { "liblog", ], + static_libs: [ + "libotautil", + ], + init_rc: [ "recovery-refresh.rc", ], diff --git a/Android.mk b/Android.mk index eff4b015d..dbd2eb788 100644 --- a/Android.mk +++ b/Android.mk @@ -126,10 +126,10 @@ LOCAL_SRC_FILES := \ adb_install.cpp \ device.cpp \ fuse_sdcard_provider.cpp \ + logging.cpp \ recovery.cpp \ recovery_main.cpp \ roots.cpp \ - rotate_logs.cpp \ LOCAL_MODULE := recovery diff --git a/common.h b/common.h index de536fdb4..3dc36a960 100644 --- a/common.h +++ b/common.h @@ -27,7 +27,9 @@ static constexpr int kRecoveryApiVersion = 3; class RecoveryUI; +struct selabel_handle; +extern struct selabel_handle* sehandle; extern RecoveryUI* ui; extern bool modified_flash; @@ -37,13 +39,6 @@ extern std::string stage; // The reason argument provided in "--reason=". extern const char* reason; -// fopen(3)'s the given file, by mounting volumes and making parent dirs as necessary. Returns the -// file pointer, or nullptr on error. -FILE* fopen_path(const std::string& path, const char* mode); - -// In turn fflush(3)'s, fsync(3)'s and fclose(3)'s the given stream. -void check_and_fclose(FILE* fp, const std::string& name); - void ui_print(const char* format, ...) __printflike(1, 2); bool is_ro_debuggable(); diff --git a/logging.cpp b/logging.cpp new file mode 100644 index 000000000..d5af72aad --- /dev/null +++ b/logging.cpp @@ -0,0 +1,243 @@ +/* + * 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 "logging.h" + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include /* for AID_SYSTEM */ +#include /* private pmsg functions */ + +#include "common.h" +#include "otautil/dirutil.h" +#include "otautil/paths.h" +#include "roots.h" + +static constexpr const char* LOG_FILE = "/cache/recovery/log"; +static constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install"; +static constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg"; +static constexpr const char* LAST_LOG_FILE = "/cache/recovery/last_log"; + +static const std::string LAST_KMSG_FILTER = "recovery/last_kmsg"; +static const std::string LAST_LOG_FILTER = "recovery/last_log"; + +// fopen(3)'s the given file, by mounting volumes and making parent dirs as necessary. Returns the +// file pointer, or nullptr on error. +static FILE* fopen_path(const std::string& path, const char* mode) { + if (ensure_path_mounted(path.c_str()) != 0) { + LOG(ERROR) << "Can't mount " << path; + return nullptr; + } + + // When writing, try to create the containing directory, if necessary. Use generous permissions, + // the system (init.rc) will reset them. + if (strchr("wa", mode[0])) { + mkdir_recursively(path, 0777, true, sehandle); + } + return fopen(path.c_str(), mode); +} + +void check_and_fclose(FILE* fp, const std::string& name) { + fflush(fp); + if (fsync(fileno(fp)) == -1) { + PLOG(ERROR) << "Failed to fsync " << name; + } + if (ferror(fp)) { + PLOG(ERROR) << "Error in " << name; + } + fclose(fp); +} + +// close a file, log an error if the error indicator is set +ssize_t logbasename(log_id_t /* id */, char /* prio */, const char* filename, const char* /* buf */, + size_t len, void* arg) { + bool* do_rotate = static_cast(arg); + if (LAST_KMSG_FILTER.find(filename) != std::string::npos || + LAST_LOG_FILTER.find(filename) != std::string::npos) { + *do_rotate = true; + } + return len; +} + +ssize_t logrotate(log_id_t id, char prio, const char* filename, const char* buf, size_t len, + void* arg) { + bool* do_rotate = static_cast(arg); + if (!*do_rotate) { + return __android_log_pmsg_file_write(id, prio, filename, buf, len); + } + + std::string name(filename); + size_t dot = name.find_last_of('.'); + std::string sub = name.substr(0, dot); + + if (LAST_KMSG_FILTER.find(sub) == std::string::npos && + LAST_LOG_FILTER.find(sub) == std::string::npos) { + return __android_log_pmsg_file_write(id, prio, filename, buf, len); + } + + // filename rotation + if (dot == std::string::npos) { + name += ".1"; + } else { + std::string number = name.substr(dot + 1); + if (!isdigit(number[0])) { + name += ".1"; + } else { + size_t i; + if (!android::base::ParseUint(number, &i)) { + LOG(ERROR) << "failed to parse uint in " << number; + return -1; + } + name = sub + "." + std::to_string(i + 1); + } + } + + return __android_log_pmsg_file_write(id, prio, name.c_str(), buf, len); +} + +// Rename last_log -> last_log.1 -> last_log.2 -> ... -> last_log.$max. +// Similarly rename last_kmsg -> last_kmsg.1 -> ... -> last_kmsg.$max. +// Overwrite any existing last_log.$max and last_kmsg.$max. +void rotate_logs(const char* last_log_file, const char* last_kmsg_file) { + // Logs should only be rotated once. + static bool rotated = false; + if (rotated) { + return; + } + rotated = true; + + for (int i = KEEP_LOG_COUNT - 1; i >= 0; --i) { + std::string old_log = android::base::StringPrintf("%s", last_log_file); + if (i > 0) { + old_log += "." + std::to_string(i); + } + std::string new_log = android::base::StringPrintf("%s.%d", last_log_file, i + 1); + // Ignore errors if old_log doesn't exist. + rename(old_log.c_str(), new_log.c_str()); + + std::string old_kmsg = android::base::StringPrintf("%s", last_kmsg_file); + if (i > 0) { + old_kmsg += "." + std::to_string(i); + } + std::string new_kmsg = android::base::StringPrintf("%s.%d", last_kmsg_file, i + 1); + rename(old_kmsg.c_str(), new_kmsg.c_str()); + } +} + +// Writes content to the current pmsg session. +static ssize_t __pmsg_write(const std::string& filename, const std::string& buf) { + return __android_log_pmsg_file_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filename.c_str(), + buf.data(), buf.size()); +} + +void copy_log_file_to_pmsg(const std::string& source, const std::string& destination) { + std::string content; + android::base::ReadFileToString(source, &content); + __pmsg_write(destination, content); +} + +// How much of the temp log we have copied to the copy in cache. +static off_t tmplog_offset = 0; + +void reset_tmplog_offset() { + tmplog_offset = 0; +} + +void copy_log_file(const std::string& source, const std::string& destination, bool append) { + FILE* dest_fp = fopen_path(destination, append ? "ae" : "we"); + if (dest_fp == nullptr) { + PLOG(ERROR) << "Can't open " << destination; + } else { + FILE* source_fp = fopen(source.c_str(), "re"); + if (source_fp != nullptr) { + if (append) { + fseeko(source_fp, tmplog_offset, SEEK_SET); // Since last write + } + char buf[4096]; + size_t bytes; + while ((bytes = fread(buf, 1, sizeof(buf), source_fp)) != 0) { + fwrite(buf, 1, bytes, dest_fp); + } + if (append) { + tmplog_offset = ftello(source_fp); + } + check_and_fclose(source_fp, source); + } + check_and_fclose(dest_fp, destination); + } +} + +void copy_logs(bool modified_flash, bool has_cache) { + // We only rotate and record the log of the current session if there are actual attempts to modify + // the flash, such as wipes, installs from BCB or menu selections. This is to avoid unnecessary + // rotation (and possible deletion) of log files, if it does not do anything loggable. + if (!modified_flash) { + return; + } + + // Always write to pmsg, this allows the OTA logs to be caught in `logcat -L`. + copy_log_file_to_pmsg(Paths::Get().temporary_log_file(), LAST_LOG_FILE); + copy_log_file_to_pmsg(Paths::Get().temporary_install_file(), LAST_INSTALL_FILE); + + // We can do nothing for now if there's no /cache partition. + if (!has_cache) { + return; + } + + ensure_path_mounted(LAST_LOG_FILE); + ensure_path_mounted(LAST_KMSG_FILE); + rotate_logs(LAST_LOG_FILE, LAST_KMSG_FILE); + + // Copy logs to cache so the system can find out what happened. + copy_log_file(Paths::Get().temporary_log_file(), LOG_FILE, true); + copy_log_file(Paths::Get().temporary_log_file(), LAST_LOG_FILE, false); + copy_log_file(Paths::Get().temporary_install_file(), LAST_INSTALL_FILE, false); + save_kernel_log(LAST_KMSG_FILE); + chmod(LOG_FILE, 0600); + chown(LOG_FILE, AID_SYSTEM, AID_SYSTEM); + chmod(LAST_KMSG_FILE, 0600); + chown(LAST_KMSG_FILE, AID_SYSTEM, AID_SYSTEM); + chmod(LAST_LOG_FILE, 0640); + chmod(LAST_INSTALL_FILE, 0644); + sync(); +} + +// Read from kernel log into buffer and write out to file. +void save_kernel_log(const char* destination) { + int klog_buf_len = klogctl(KLOG_SIZE_BUFFER, 0, 0); + if (klog_buf_len <= 0) { + PLOG(ERROR) << "Error getting klog size"; + return; + } + + std::string buffer(klog_buf_len, 0); + int n = klogctl(KLOG_READ_ALL, &buffer[0], klog_buf_len); + if (n == -1) { + PLOG(ERROR) << "Error in reading klog"; + return; + } + buffer.resize(n); + android::base::WriteStringToFile(buffer, destination); +} diff --git a/logging.h b/logging.h new file mode 100644 index 000000000..3cfbc7af6 --- /dev/null +++ b/logging.h @@ -0,0 +1,50 @@ +/* + * 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 _LOGGING_H +#define _LOGGING_H + +#include +#include + +#include + +#include + +static constexpr int KEEP_LOG_COUNT = 10; + +ssize_t logbasename(log_id_t id, char prio, const char* filename, const char* buf, size_t len, + void* arg); + +ssize_t logrotate(log_id_t id, char prio, const char* filename, const char* buf, size_t len, + void* arg); + +// Rename last_log -> last_log.1 -> last_log.2 -> ... -> last_log.$max. +// Similarly rename last_kmsg -> last_kmsg.1 -> ... -> last_kmsg.$max. +// Overwrite any existing last_log.$max and last_kmsg.$max. +void rotate_logs(const char* last_log_file, const char* last_kmsg_file); + +// In turn fflush(3)'s, fsync(3)'s and fclose(3)'s the given stream. +void check_and_fclose(FILE* fp, const std::string& name); + +void copy_log_file_to_pmsg(const std::string& source, const std::string& destination); +void copy_log_file(const std::string& source, const std::string& destination, bool append); +void copy_logs(bool modified_flash, bool has_cache); +void reset_tmplog_offset(); + +void save_kernel_log(const char* destination); + +#endif //_LOGGING_H diff --git a/recovery-persist.cpp b/recovery-persist.cpp index dbce7ff74..d3ade6260 100644 --- a/recovery-persist.cpp +++ b/recovery-persist.cpp @@ -41,7 +41,7 @@ #include #include /* private pmsg functions */ -#include "rotate_logs.h" +#include "logging.h" static const char *LAST_LOG_FILE = "/data/misc/recovery/last_log"; static const char *LAST_PMSG_FILE = "/sys/fs/pstore/pmsg-ramoops-0"; diff --git a/recovery-refresh.cpp b/recovery-refresh.cpp index 14565d3f4..aee1ca592 100644 --- a/recovery-refresh.cpp +++ b/recovery-refresh.cpp @@ -42,7 +42,7 @@ #include /* private pmsg functions */ -#include "rotate_logs.h" +#include "logging.h" int main(int argc, char **argv) { static const char filter[] = "recovery/"; diff --git a/recovery.cpp b/recovery.cpp index 00f38596c..0ab34197f 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -53,8 +52,6 @@ #include #include /* for property_list */ #include -#include /* for AID_SYSTEM */ -#include /* private pmsg functions */ #include #include #include @@ -66,21 +63,19 @@ #include "fuse_sdcard_provider.h" #include "fuse_sideload.h" #include "install.h" +#include "logging.h" #include "minui/minui.h" #include "otautil/dirutil.h" #include "otautil/error_code.h" #include "otautil/paths.h" #include "otautil/sysutil.h" #include "roots.h" -#include "rotate_logs.h" #include "screen_ui.h" #include "stub_ui.h" #include "ui.h" static constexpr const char* CACHE_LOG_DIR = "/cache/recovery"; static constexpr const char* COMMAND_FILE = "/cache/recovery/command"; -static constexpr const char* LOG_FILE = "/cache/recovery/log"; -static constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install"; static constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg"; static constexpr const char* LAST_LOG_FILE = "/cache/recovery/last_log"; static constexpr const char* LOCALE_FILE = "/cache/recovery/last_locale"; @@ -149,31 +144,6 @@ struct selabel_handle* sehandle; * 7b. the user reboots (pulling the battery, etc) into the main system */ -FILE* fopen_path(const std::string& path, const char* mode) { - if (ensure_path_mounted(path.c_str()) != 0) { - LOG(ERROR) << "Can't mount " << path; - return nullptr; - } - - // When writing, try to create the containing directory, if necessary. Use generous permissions, - // the system (init.rc) will reset them. - if (strchr("wa", mode[0])) { - mkdir_recursively(path, 0777, true, sehandle); - } - return fopen(path.c_str(), mode); -} - -void check_and_fclose(FILE* fp, const std::string& name) { - fflush(fp); - if (fsync(fileno(fp)) == -1) { - PLOG(ERROR) << "Failed to fsync " << name; - } - if (ferror(fp)) { - PLOG(ERROR) << "Error in " << name; - } - fclose(fp); -} - bool is_ro_debuggable() { return android::base::GetBoolProperty("ro.debuggable", false); } @@ -259,98 +229,6 @@ static void set_sdcard_update_bootloader_message() { } } -// Read from kernel log into buffer and write out to file. -static void save_kernel_log(const char* destination) { - int klog_buf_len = klogctl(KLOG_SIZE_BUFFER, 0, 0); - if (klog_buf_len <= 0) { - PLOG(ERROR) << "Error getting klog size"; - return; - } - - std::string buffer(klog_buf_len, 0); - int n = klogctl(KLOG_READ_ALL, &buffer[0], klog_buf_len); - if (n == -1) { - PLOG(ERROR) << "Error in reading klog"; - return; - } - buffer.resize(n); - android::base::WriteStringToFile(buffer, destination); -} - -// Writes content to the current pmsg session. -static ssize_t __pmsg_write(const std::string& filename, const std::string& buf) { - return __android_log_pmsg_file_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, filename.c_str(), - buf.data(), buf.size()); -} - -static void copy_log_file_to_pmsg(const std::string& source, const std::string& destination) { - std::string content; - android::base::ReadFileToString(source, &content); - __pmsg_write(destination, content); -} - -// How much of the temp log we have copied to the copy in cache. -static off_t tmplog_offset = 0; - -static void copy_log_file(const std::string& source, const std::string& destination, bool append) { - FILE* dest_fp = fopen_path(destination, append ? "ae" : "we"); - if (dest_fp == nullptr) { - PLOG(ERROR) << "Can't open " << destination; - } else { - FILE* source_fp = fopen(source.c_str(), "re"); - if (source_fp != nullptr) { - if (append) { - fseeko(source_fp, tmplog_offset, SEEK_SET); // Since last write - } - char buf[4096]; - size_t bytes; - while ((bytes = fread(buf, 1, sizeof(buf), source_fp)) != 0) { - fwrite(buf, 1, bytes, dest_fp); - } - if (append) { - tmplog_offset = ftello(source_fp); - } - check_and_fclose(source_fp, source); - } - check_and_fclose(dest_fp, destination); - } -} - -static void copy_logs() { - // We only rotate and record the log of the current session if there are actual attempts to modify - // the flash, such as wipes, installs from BCB or menu selections. This is to avoid unnecessary - // rotation (and possible deletion) of log files, if it does not do anything loggable. - if (!modified_flash) { - return; - } - - // Always write to pmsg, this allows the OTA logs to be caught in `logcat -L`. - copy_log_file_to_pmsg(Paths::Get().temporary_log_file(), LAST_LOG_FILE); - copy_log_file_to_pmsg(Paths::Get().temporary_install_file(), LAST_INSTALL_FILE); - - // We can do nothing for now if there's no /cache partition. - if (!has_cache) { - return; - } - - ensure_path_mounted(LAST_LOG_FILE); - ensure_path_mounted(LAST_KMSG_FILE); - rotate_logs(LAST_LOG_FILE, LAST_KMSG_FILE); - - // Copy logs to cache so the system can find out what happened. - copy_log_file(Paths::Get().temporary_log_file(), LOG_FILE, true); - copy_log_file(Paths::Get().temporary_log_file(), LAST_LOG_FILE, false); - copy_log_file(Paths::Get().temporary_install_file(), LAST_INSTALL_FILE, false); - save_kernel_log(LAST_KMSG_FILE); - chmod(LOG_FILE, 0600); - chown(LOG_FILE, AID_SYSTEM, AID_SYSTEM); - chmod(LAST_KMSG_FILE, 0600); - chown(LAST_KMSG_FILE, AID_SYSTEM, AID_SYSTEM); - chmod(LAST_LOG_FILE, 0640); - chmod(LAST_INSTALL_FILE, 0644); - sync(); -} - // Clear the recovery command and prepare to boot a (hopefully working) system, // copy our log file to cache as well (for the system to read). This function is // idempotent: call it as many times as you like. @@ -366,7 +244,7 @@ static void finish_recovery() { } } - copy_logs(); + copy_logs(modified_flash, has_cache); // Reset to normal system boot so recovery won't cycle indefinitely. std::string err; @@ -482,8 +360,8 @@ static bool erase_volume(const char* volume) { // Any part of the log we'd copied to cache is now gone. // Reset the pointer so we copy from the beginning of the temp // log. - tmplog_offset = 0; - copy_logs(); + reset_tmplog_offset(); + copy_logs(modified_flash, has_cache); } return (result == 0); @@ -1000,7 +878,7 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) { if (status != INSTALL_SUCCESS) { ui->SetBackground(RecoveryUI::ERROR); ui->Print("Installation aborted.\n"); - copy_logs(); + copy_logs(modified_flash, has_cache); } else if (!ui->IsTextVisible()) { return Device::NO_ACTION; // reboot if logs aren't visible } else { @@ -1394,7 +1272,7 @@ int start_recovery(int argc, char** argv) { // RETRY_LIMIT times before we abandon this OTA update. static constexpr int RETRY_LIMIT = 4; if (status == INSTALL_RETRY && retry_count < RETRY_LIMIT) { - copy_logs(); + copy_logs(modified_flash, has_cache); retry_count += 1; set_retry_bootloader_message(retry_count, args); // Print retry count on screen. diff --git a/recovery_main.cpp b/recovery_main.cpp index 9f579f7cd..3147511ee 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -24,10 +24,10 @@ #include /* private pmsg functions */ #include "common.h" +#include "logging.h" #include "minadbd/minadbd.h" #include "otautil/paths.h" #include "private/recovery.h" -#include "rotate_logs.h" #include "ui.h" static void UiLogger(android::base::LogId /* id */, android::base::LogSeverity severity, diff --git a/rotate_logs.cpp b/rotate_logs.cpp deleted file mode 100644 index da008792c..000000000 --- a/rotate_logs.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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 "rotate_logs.h" - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include /* private pmsg functions */ - -static const std::string LAST_KMSG_FILTER = "recovery/last_kmsg"; -static const std::string LAST_LOG_FILTER = "recovery/last_log"; - -ssize_t logbasename(log_id_t /* id */, char /* prio */, const char* filename, const char* /* buf */, - size_t len, void* arg) { - bool* do_rotate = static_cast(arg); - if (LAST_KMSG_FILTER.find(filename) != std::string::npos || - LAST_LOG_FILTER.find(filename) != std::string::npos) { - *do_rotate = true; - } - return len; -} - -ssize_t logrotate(log_id_t id, char prio, const char* filename, const char* buf, size_t len, - void* arg) { - bool* do_rotate = static_cast(arg); - if (!*do_rotate) { - return __android_log_pmsg_file_write(id, prio, filename, buf, len); - } - - std::string name(filename); - size_t dot = name.find_last_of('.'); - std::string sub = name.substr(0, dot); - - if (LAST_KMSG_FILTER.find(sub) == std::string::npos && - LAST_LOG_FILTER.find(sub) == std::string::npos) { - return __android_log_pmsg_file_write(id, prio, filename, buf, len); - } - - // filename rotation - if (dot == std::string::npos) { - name += ".1"; - } else { - std::string number = name.substr(dot + 1); - if (!isdigit(number[0])) { - name += ".1"; - } else { - size_t i; - if (!android::base::ParseUint(number, &i)) { - LOG(ERROR) << "failed to parse uint in " << number; - return -1; - } - name = sub + "." + std::to_string(i + 1); - } - } - - return __android_log_pmsg_file_write(id, prio, name.c_str(), buf, len); -} - -// Rename last_log -> last_log.1 -> last_log.2 -> ... -> last_log.$max. -// Similarly rename last_kmsg -> last_kmsg.1 -> ... -> last_kmsg.$max. -// Overwrite any existing last_log.$max and last_kmsg.$max. -void rotate_logs(const char* last_log_file, const char* last_kmsg_file) { - // Logs should only be rotated once. - static bool rotated = false; - if (rotated) { - return; - } - rotated = true; - - for (int i = KEEP_LOG_COUNT - 1; i >= 0; --i) { - std::string old_log = android::base::StringPrintf("%s", last_log_file); - if (i > 0) { - old_log += "." + std::to_string(i); - } - std::string new_log = android::base::StringPrintf("%s.%d", last_log_file, i + 1); - // Ignore errors if old_log doesn't exist. - rename(old_log.c_str(), new_log.c_str()); - - std::string old_kmsg = android::base::StringPrintf("%s", last_kmsg_file); - if (i > 0) { - old_kmsg += "." + std::to_string(i); - } - std::string new_kmsg = android::base::StringPrintf("%s.%d", last_kmsg_file, i + 1); - rename(old_kmsg.c_str(), new_kmsg.c_str()); - } -} diff --git a/rotate_logs.h b/rotate_logs.h deleted file mode 100644 index 007c33d44..000000000 --- a/rotate_logs.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 _ROTATE_LOGS_H -#define _ROTATE_LOGS_H - -#include -#include - -#include - -static constexpr int KEEP_LOG_COUNT = 10; - -ssize_t logbasename(log_id_t id, char prio, const char* filename, const char* buf, size_t len, - void* arg); - -ssize_t logrotate(log_id_t id, char prio, const char* filename, const char* buf, size_t len, - void* arg); - -// Rename last_log -> last_log.1 -> last_log.2 -> ... -> last_log.$max. -// Similarly rename last_kmsg -> last_kmsg.1 -> ... -> last_kmsg.$max. -// Overwrite any existing last_log.$max and last_kmsg.$max. -void rotate_logs(const char* last_log_file, const char* last_kmsg_file); - -#endif //_ROTATE_LOG_H -- cgit v1.2.3 From 6a6480496517dc9343b80380637b40094b72d3a4 Mon Sep 17 00:00:00 2001 From: Jerry Zhang Date: Fri, 4 May 2018 11:24:10 -0700 Subject: recovery: Refactor common setup into main() Move more common setup into the main function. Main() handles all 1 time setup, such as ui, logging, and secontext. Recovery_main() takes in command line arguments, does any necessary recovery work, and can be called multiple times from main(). Test: Recovery works Bug: 78793464 Change-Id: I2d2595fc342b4ddfa80f4e06b30e44263132acd9 --- common.h | 1 + private/recovery.h | 19 ----- recovery.cpp | 172 ++-------------------------------------- recovery.h | 24 ++++++ recovery_main.cpp | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 253 insertions(+), 189 deletions(-) delete mode 100644 private/recovery.h create mode 100644 recovery.h diff --git a/common.h b/common.h index 3dc36a960..c24431bd1 100644 --- a/common.h +++ b/common.h @@ -32,6 +32,7 @@ struct selabel_handle; extern struct selabel_handle* sehandle; extern RecoveryUI* ui; extern bool modified_flash; +extern bool has_cache; // The current stage, e.g. "1/2". extern std::string stage; diff --git a/private/recovery.h b/private/recovery.h deleted file mode 100644 index 5b2ca4b3f..000000000 --- a/private/recovery.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#pragma once - -int start_recovery(int argc, char** argv); diff --git a/recovery.cpp b/recovery.cpp index f03cec3fe..2360057d0 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "private/recovery.h" +#include "recovery.h" #include #include @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -49,12 +48,8 @@ #include #include #include -#include #include /* for property_list */ #include -#include -#include -#include #include #include "adb_install.h" @@ -70,7 +65,6 @@ #include "otautil/sysutil.h" #include "roots.h" #include "screen_ui.h" -#include "stub_ui.h" #include "ui.h" static constexpr const char* CACHE_LOG_DIR = "/cache/recovery"; @@ -88,13 +82,9 @@ static constexpr const char* SDCARD_ROOT = "/sdcard"; // into target_files.zip. Assert the version defined in code and in Android.mk are consistent. static_assert(kRecoveryApiVersion == RECOVERY_API_VERSION, "Mismatching recovery API versions."); -static bool has_cache = false; - -RecoveryUI* ui = nullptr; bool modified_flash = false; std::string stage; const char* reason = nullptr; -struct selabel_handle* sehandle; /* * The recovery tool communicates with the main system through /cache files. @@ -146,77 +136,6 @@ bool is_ro_debuggable() { return android::base::GetBoolProperty("ro.debuggable", false); } -// command line args come from, in decreasing precedence: -// - the actual command line -// - the bootloader control block (one per line, after "recovery") -// - the contents of COMMAND_FILE (one per line) -static std::vector get_args(const int argc, char** const argv) { - CHECK_GT(argc, 0); - - bootloader_message boot = {}; - std::string err; - if (!read_bootloader_message(&boot, &err)) { - LOG(ERROR) << err; - // If fails, leave a zeroed bootloader_message. - boot = {}; - } - stage = std::string(boot.stage); - - if (boot.command[0] != 0) { - std::string boot_command = std::string(boot.command, sizeof(boot.command)); - LOG(INFO) << "Boot command: " << boot_command; - } - - if (boot.status[0] != 0) { - std::string boot_status = std::string(boot.status, sizeof(boot.status)); - LOG(INFO) << "Boot status: " << boot_status; - } - - std::vector args(argv, argv + argc); - - // --- if arguments weren't supplied, look in the bootloader control block - if (args.size() == 1) { - boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination - std::string boot_recovery(boot.recovery); - std::vector tokens = android::base::Split(boot_recovery, "\n"); - if (!tokens.empty() && tokens[0] == "recovery") { - for (auto it = tokens.begin() + 1; it != tokens.end(); it++) { - // Skip empty and '\0'-filled tokens. - if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it)); - } - LOG(INFO) << "Got " << args.size() << " arguments from boot message"; - } else if (boot.recovery[0] != 0) { - LOG(ERROR) << "Bad boot message: \"" << boot_recovery << "\""; - } - } - - // --- if that doesn't work, try the command file (if we have /cache). - if (args.size() == 1 && has_cache) { - std::string content; - if (ensure_path_mounted(COMMAND_FILE) == 0 && - android::base::ReadFileToString(COMMAND_FILE, &content)) { - std::vector tokens = android::base::Split(content, "\n"); - // All the arguments in COMMAND_FILE are needed (unlike the BCB message, - // COMMAND_FILE doesn't use filename as the first argument). - for (auto it = tokens.begin(); it != tokens.end(); it++) { - // Skip empty and '\0'-filled tokens. - if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it)); - } - LOG(INFO) << "Got " << args.size() << " arguments from " << COMMAND_FILE; - } - } - - // Write the arguments (excluding the filename in args[0]) back into the - // bootloader control block. So the device will always boot into recovery to - // finish the pending work, until finish_recovery() is called. - std::vector options(args.cbegin() + 1, args.cend()); - if (!update_bootloader_message(options, &err)) { - LOG(ERROR) << "Failed to set BCB message: " << err; - } - - return args; -} - // Set the BCB to reboot back into recovery (it won't resume the install from // sdcard though). static void set_sdcard_update_bootloader_message() { @@ -921,21 +840,6 @@ static void print_property(const char* key, const char* name, void* /* cookie */ printf("%s=%s\n", key, name); } -static std::string load_locale_from_cache() { - if (ensure_path_mounted(LOCALE_FILE) != 0) { - LOG(ERROR) << "Can't mount " << LOCALE_FILE; - return ""; - } - - std::string content; - if (!android::base::ReadFileToString(LOCALE_FILE, &content)) { - PLOG(ERROR) << "Can't read " << LOCALE_FILE; - return ""; - } - - return android::base::Trim(content); -} - void ui_print(const char* format, ...) { std::string buffer; va_list ap; @@ -1079,15 +983,7 @@ static void log_failure_code(ErrorCode code, const std::string& update_package) LOG(INFO) << log_content; } -int start_recovery(int argc, char** argv) { - time_t start = time(nullptr); - - printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start)); - - load_volume_table(); - has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr; - - std::vector args = get_args(argc, argv); +Device::BuiltinAction start_recovery(Device* device, const std::vector& args) { std::vector args_to_parse(args.size()); std::transform(args.cbegin(), args.cend(), args_to_parse.begin(), [](const std::string& arg) { return const_cast(arg.c_str()); }); @@ -1117,7 +1013,6 @@ int start_recovery(int argc, char** argv) { bool should_wipe_cache = false; bool should_wipe_ab = false; size_t wipe_package_size = 0; - bool show_text = false; bool sideload = false; bool sideload_auto_reboot = false; bool just_exit = false; @@ -1132,7 +1027,7 @@ int start_recovery(int argc, char** argv) { &option_index)) != -1) { switch (arg) { case 't': - show_text = true; + // Handled in recovery_main.cpp break; case 'x': just_exit = true; @@ -1140,7 +1035,7 @@ int start_recovery(int argc, char** argv) { case 0: { std::string option = OPTIONS[option_index].name; if (option == "locale") { - locale = optarg; + // Handled in recovery_main.cpp } else if (option == "prompt_and_wipe_data") { should_prompt_and_wipe_data = true; } else if (option == "reason") { @@ -1175,37 +1070,9 @@ int start_recovery(int argc, char** argv) { } } - if (locale.empty()) { - if (has_cache) { - locale = load_locale_from_cache(); - } - - if (locale.empty()) { - static constexpr const char* DEFAULT_LOCALE = "en-US"; - locale = DEFAULT_LOCALE; - } - } - - printf("locale is [%s]\n", locale.c_str()); printf("stage is [%s]\n", stage.c_str()); printf("reason is [%s]\n", reason); - Device* device = make_device(); - if (android::base::GetBoolProperty("ro.boot.quiescent", false)) { - printf("Quiescent recovery mode.\n"); - device->ResetUI(new StubRecoveryUI()); - } else { - if (!device->GetUI()->Init(locale)) { - printf("Failed to initialize UI; using stub UI instead.\n"); - device->ResetUI(new StubRecoveryUI()); - } - } - ui = device->GetUI(); - - if (!has_cache) { - device->RemoveMenuItemForAction(Device::WIPE_CACHE); - } - // Set background string to "installing security update" for security update, // otherwise set it to "installing system update". ui->SetSystemUpdateText(security_update); @@ -1215,15 +1082,6 @@ int start_recovery(int argc, char** argv) { ui->SetStage(st_cur, st_max); } - ui->SetBackground(RecoveryUI::NONE); - if (show_text) ui->ShowText(true); - - sehandle = selinux_android_file_context_handle(); - selinux_android_set_sehandle(sehandle); - if (!sehandle) { - ui->Print("Warning: No file_contexts\n"); - } - device->StartRecovery(); printf("Command:"); @@ -1373,25 +1231,5 @@ int start_recovery(int argc, char** argv) { // Save logs and clean up before rebooting or shutting down. finish_recovery(); - switch (after) { - case Device::SHUTDOWN: - ui->Print("Shutting down...\n"); - android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,"); - break; - - case Device::REBOOT_BOOTLOADER: - ui->Print("Rebooting to bootloader...\n"); - android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader"); - break; - - default: - ui->Print("Rebooting...\n"); - reboot("reboot,"); - break; - } - while (true) { - pause(); - } - // Should be unreachable. - return EXIT_SUCCESS; + return after; } diff --git a/recovery.h b/recovery.h new file mode 100644 index 000000000..00e22daa6 --- /dev/null +++ b/recovery.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 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. + */ + +#pragma once + +#include +#include + +#include "device.h" + +Device::BuiltinAction start_recovery(Device* device, const std::vector& args); diff --git a/recovery_main.cpp b/recovery_main.cpp index 3147511ee..e21c782d0 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -14,22 +14,57 @@ * limitations under the License. */ +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include #include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include /* private pmsg functions */ +#include +#include +#include #include "common.h" +#include "device.h" #include "logging.h" #include "minadbd/minadbd.h" #include "otautil/paths.h" -#include "private/recovery.h" +#include "otautil/sysutil.h" +#include "recovery.h" +#include "roots.h" +#include "stub_ui.h" #include "ui.h" +static constexpr const char* COMMAND_FILE = "/cache/recovery/command"; +static constexpr const char* LOCALE_FILE = "/cache/recovery/last_locale"; + +static constexpr const char* CACHE_ROOT = "/cache"; + +bool has_cache = false; + +RecoveryUI* ui = nullptr; +struct selabel_handle* sehandle; + static void UiLogger(android::base::LogId /* id */, android::base::LogSeverity severity, const char* /* tag */, const char* /* file */, unsigned int /* line */, const char* message) { @@ -41,6 +76,92 @@ static void UiLogger(android::base::LogId /* id */, android::base::LogSeverity s } } +// command line args come from, in decreasing precedence: +// - the actual command line +// - the bootloader control block (one per line, after "recovery") +// - the contents of COMMAND_FILE (one per line) +static std::vector get_args(const int argc, char** const argv) { + CHECK_GT(argc, 0); + + bootloader_message boot = {}; + std::string err; + if (!read_bootloader_message(&boot, &err)) { + LOG(ERROR) << err; + // If fails, leave a zeroed bootloader_message. + boot = {}; + } + stage = std::string(boot.stage); + + if (boot.command[0] != 0) { + std::string boot_command = std::string(boot.command, sizeof(boot.command)); + LOG(INFO) << "Boot command: " << boot_command; + } + + if (boot.status[0] != 0) { + std::string boot_status = std::string(boot.status, sizeof(boot.status)); + LOG(INFO) << "Boot status: " << boot_status; + } + + std::vector args(argv, argv + argc); + + // --- if arguments weren't supplied, look in the bootloader control block + if (args.size() == 1) { + boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination + std::string boot_recovery(boot.recovery); + std::vector tokens = android::base::Split(boot_recovery, "\n"); + if (!tokens.empty() && tokens[0] == "recovery") { + for (auto it = tokens.begin() + 1; it != tokens.end(); it++) { + // Skip empty and '\0'-filled tokens. + if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it)); + } + LOG(INFO) << "Got " << args.size() << " arguments from boot message"; + } else if (boot.recovery[0] != 0) { + LOG(ERROR) << "Bad boot message: \"" << boot_recovery << "\""; + } + } + + // --- if that doesn't work, try the command file (if we have /cache). + if (args.size() == 1 && has_cache) { + std::string content; + if (ensure_path_mounted(COMMAND_FILE) == 0 && + android::base::ReadFileToString(COMMAND_FILE, &content)) { + std::vector tokens = android::base::Split(content, "\n"); + // All the arguments in COMMAND_FILE are needed (unlike the BCB message, + // COMMAND_FILE doesn't use filename as the first argument). + for (auto it = tokens.begin(); it != tokens.end(); it++) { + // Skip empty and '\0'-filled tokens. + if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it)); + } + LOG(INFO) << "Got " << args.size() << " arguments from " << COMMAND_FILE; + } + } + + // Write the arguments (excluding the filename in args[0]) back into the + // bootloader control block. So the device will always boot into recovery to + // finish the pending work, until finish_recovery() is called. + std::vector options(args.cbegin() + 1, args.cend()); + if (!update_bootloader_message(options, &err)) { + LOG(ERROR) << "Failed to set BCB message: " << err; + } + + return args; +} + +static std::string load_locale_from_cache() { + if (ensure_path_mounted(LOCALE_FILE) != 0) { + LOG(ERROR) << "Can't mount " << LOCALE_FILE; + return ""; + } + + std::string content; + if (!android::base::ReadFileToString(LOCALE_FILE, &content)) { + PLOG(ERROR) << "Can't read " << LOCALE_FILE; + return ""; + } + + return android::base::Trim(content); +} + static void redirect_stdio(const char* filename) { int pipefd[2]; if (pipe(pipefd) == -1) { @@ -154,9 +275,108 @@ int main(int argc, char** argv) { return 0; } + time_t start = time(nullptr); + // redirect_stdio should be called only in non-sideload mode. Otherwise we may have two logger // instances with different timestamps. redirect_stdio(Paths::Get().temporary_log_file().c_str()); - return start_recovery(argc, argv); + printf("Starting recovery (pid %d) on %s", getpid(), ctime(&start)); + + load_volume_table(); + has_cache = volume_for_mount_point(CACHE_ROOT) != nullptr; + + std::vector args = get_args(argc, argv); + std::vector args_to_parse(args.size()); + std::transform(args.cbegin(), args.cend(), args_to_parse.begin(), + [](const std::string& arg) { return const_cast(arg.c_str()); }); + + static constexpr struct option OPTIONS[] = { + { "locale", required_argument, nullptr, 0 }, + { "show_text", no_argument, nullptr, 't' }, + { nullptr, 0, nullptr, 0 }, + }; + + bool show_text = false; + std::string locale; + + int arg; + int option_index; + while ((arg = getopt_long(args_to_parse.size(), args_to_parse.data(), "", OPTIONS, + &option_index)) != -1) { + switch (arg) { + case 't': + show_text = true; + break; + case 0: { + std::string option = OPTIONS[option_index].name; + if (option == "locale") { + locale = optarg; + } + break; + } + } + } + + if (locale.empty()) { + if (has_cache) { + locale = load_locale_from_cache(); + } + + if (locale.empty()) { + static constexpr const char* DEFAULT_LOCALE = "en-US"; + locale = DEFAULT_LOCALE; + } + } + + printf("locale is [%s]\n", locale.c_str()); + + Device* device = make_device(); + if (android::base::GetBoolProperty("ro.boot.quiescent", false)) { + printf("Quiescent recovery mode.\n"); + device->ResetUI(new StubRecoveryUI()); + } else { + if (!device->GetUI()->Init(locale)) { + printf("Failed to initialize UI; using stub UI instead.\n"); + device->ResetUI(new StubRecoveryUI()); + } + } + ui = device->GetUI(); + + if (!has_cache) { + device->RemoveMenuItemForAction(Device::WIPE_CACHE); + } + + ui->SetBackground(RecoveryUI::NONE); + if (show_text) ui->ShowText(true); + + sehandle = selinux_android_file_context_handle(); + selinux_android_set_sehandle(sehandle); + if (!sehandle) { + ui->Print("Warning: No file_contexts\n"); + } + + Device::BuiltinAction after = start_recovery(device, args); + + switch (after) { + case Device::SHUTDOWN: + ui->Print("Shutting down...\n"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,"); + break; + + case Device::REBOOT_BOOTLOADER: + ui->Print("Rebooting to bootloader...\n"); + android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader"); + break; + + default: + ui->Print("Rebooting...\n"); + reboot("reboot,"); + break; + } + while (true) { + pause(); + } + // Should be unreachable. + return EXIT_SUCCESS; } -- cgit v1.2.3 From fd0ace8f6ee5b098c400af03bfe31797994476cd Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Wed, 11 Oct 2017 20:25:36 -0700 Subject: Move stuff from recovery into librecovery. Move most source files into librecovery so they become testable. Only recovery_main.cpp and logging.cpp are built into recovery module, as they perform one-time setup (e.g. setting up logger). Test: `mmma -j bootable/recovery` with aosp_{angler,bullhead,fugu,dragon,marlin}-userdebug Test: recovery_host_test; recovery_unit_test; recovery_component_test; recovery_manual_test Test: Build and boot into recovery image on angler. Change-Id: Ic4444f87a2f123557c71085f81dc2b2764c05ed8 (cherry picked from commit bf4c006d7bc8a4517c82399bbffd9cb09971c0b4) --- Android.mk | 107 +++++++++++++++++++++++++++---------------------------- tests/Android.mk | 16 +++++++-- 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/Android.mk b/Android.mk index 09feba289..efd7462c2 100644 --- a/Android.mk +++ b/Android.mk @@ -97,12 +97,61 @@ endif include $(BUILD_STATIC_LIBRARY) +# Health HAL dependency +health_hal_static_libraries := \ + android.hardware.health@2.0-impl \ + android.hardware.health@2.0 \ + android.hardware.health@1.0 \ + android.hardware.health@1.0-convert \ + libhealthstoragedefault \ + libhidltransport \ + libhidlbase \ + libhwbinder_noltopgo \ + libvndksupport \ + libbatterymonitor + +librecovery_static_libraries := \ + $(TARGET_RECOVERY_UI_LIB) \ + libbootloader_message \ + libfusesideload \ + libminadbd \ + librecovery_ui \ + libminui \ + libverifier \ + libotautil \ + $(health_hal_static_libraries) \ + libasyncio \ + libcrypto_utils \ + libcrypto \ + libext4_utils \ + libfs_mgr \ + libpng \ + libsparse \ + libvintf_recovery \ + libvintf \ + libhidl-gen-utils \ + libtinyxml2 \ + libziparchive \ + libbase \ + libutils \ + libcutils \ + liblog \ + libselinux \ + libz \ + # librecovery (static library) # =============================== include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - install.cpp + adb_install.cpp \ + fuse_sdcard_provider.cpp \ + install.cpp \ + recovery.cpp \ + roots.cpp \ + +LOCAL_C_INCLUDES := \ + system/vold \ LOCAL_CFLAGS := $(recovery_common_cflags) @@ -113,13 +162,7 @@ endif LOCAL_MODULE := librecovery LOCAL_STATIC_LIBRARIES := \ - libminui \ - libotautil \ - libvintf_recovery \ - libcrypto_utils \ - libcrypto \ - libbase \ - libziparchive \ + $(librecovery_static_libraries) include $(BUILD_STATIC_LIBRARY) @@ -128,12 +171,8 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - adb_install.cpp \ - fuse_sdcard_provider.cpp \ logging.cpp \ - recovery.cpp \ recovery_main.cpp \ - roots.cpp \ LOCAL_MODULE := recovery @@ -147,51 +186,9 @@ LOCAL_USE_CLANG_LLD := false LOCAL_CFLAGS := $(recovery_common_cflags) -LOCAL_C_INCLUDES += \ - system/vold \ - -# Health HAL dependency LOCAL_STATIC_LIBRARIES := \ - android.hardware.health@2.0-impl \ - android.hardware.health@2.0 \ - android.hardware.health@1.0 \ - android.hardware.health@1.0-convert \ - libhealthstoragedefault \ - libhidltransport \ - libhidlbase \ - libhwbinder_noltopgo \ - libvndksupport \ - libbatterymonitor - -LOCAL_STATIC_LIBRARIES += \ librecovery \ - $(TARGET_RECOVERY_UI_LIB) \ - libbootloader_message \ - libfusesideload \ - libminadbd \ - librecovery_ui \ - libminui \ - libverifier \ - libotautil \ - libasyncio \ - libbatterymonitor \ - libcrypto_utils \ - libcrypto \ - libext4_utils \ - libfs_mgr \ - libpng \ - libsparse \ - libvintf_recovery \ - libvintf \ - libhidl-gen-utils \ - libtinyxml2 \ - libziparchive \ - libbase \ - libutils \ - libcutils \ - liblog \ - libselinux \ - libz \ + $(librecovery_static_libraries) LOCAL_HAL_STATIC_LIBRARIES := libhealthd diff --git a/tests/Android.mk b/tests/Android.mk index cdc5b523a..efe46b8ee 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -150,6 +150,18 @@ libupdater_static_libraries := \ libbrotli \ $(tune2fs_static_libraries) +health_hal_static_libraries := \ + android.hardware.health@2.0-impl \ + android.hardware.health@2.0 \ + android.hardware.health@1.0 \ + android.hardware.health@1.0-convert \ + libhealthstoragedefault \ + libhidltransport \ + libhidlbase \ + libhwbinder_noltopgo \ + libvndksupport \ + libbatterymonitor + librecovery_static_libraries := \ librecovery \ $(TARGET_RECOVERY_UI_LIB) \ @@ -160,8 +172,8 @@ librecovery_static_libraries := \ libminui \ libverifier \ libotautil \ + $(health_hal_static_libraries) \ libasyncio \ - libbatterymonitor \ libcrypto_utils \ libcrypto \ libext4_utils \ @@ -174,8 +186,8 @@ librecovery_static_libraries := \ libtinyxml2 \ libziparchive \ libbase \ - libcutils \ libutils \ + libcutils \ liblog \ libselinux \ libz \ -- cgit v1.2.3