screen_ui.cpp revision 80a7a4642be31db7ecd5eaa9e62b78deaa461146
1c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project/*
2211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker * Copyright (C) 2011 The Android Open Source Project
3c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project *
4c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project * you may not use this file except in compliance with the License.
6c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project * You may obtain a copy of the License at
7c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project *
8c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project *
10c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project * See the License for the specific language governing permissions and
14c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project * limitations under the License.
15c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project */
16c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
176ce4a326efae4abb108e19899f4d7776abc362daDoug Zongker#include <errno.h>
186ce4a326efae4abb108e19899f4d7776abc362daDoug Zongker#include <fcntl.h>
19c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <linux/input.h>
20c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <pthread.h>
21c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <stdarg.h>
22c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <stdio.h>
23c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <stdlib.h>
24c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <string.h>
256ce4a326efae4abb108e19899f4d7776abc362daDoug Zongker#include <sys/stat.h>
26c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <sys/time.h>
276ce4a326efae4abb108e19899f4d7776abc362daDoug Zongker#include <sys/types.h>
28c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <time.h>
29c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include <unistd.h>
30c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
31c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include "common.h"
3232a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker#include "device.h"
33c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project#include "minui/minui.h"
34211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker#include "screen_ui.h"
3532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker#include "ui.h"
36c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
3755a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongkerstatic int char_width;
3855a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongkerstatic int char_height;
39c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
40211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// There's only (at most) one of these objects, and global callbacks
41211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// (for pthread_create, and the input event system) need to find it,
42211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// so use a global variable.
43211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerstatic ScreenRecoveryUI* self = NULL;
44c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
456809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// Return the current time as a double (including fractions of a second).
466809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongkerstatic double now() {
476809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    struct timeval tv;
486809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    gettimeofday(&tv, NULL);
496809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    return tv.tv_sec + tv.tv_usec / 1000000.0;
506809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker}
516809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
52211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug ZongkerScreenRecoveryUI::ScreenRecoveryUI() :
53211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    currentIcon(NONE),
54211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    installingFrame(0),
555fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker    rtl_locale(false),
56211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressBarType(EMPTY),
57211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeStart(0),
58211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeSize(0),
59211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progress(0),
60211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pagesIdentical(false),
61211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_cols(0),
62211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_rows(0),
63211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_col(0),
64211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_row(0),
65211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_top(0),
66211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    show_text(false),
67211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    show_text_ever(false),
68211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    show_menu(false),
69211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    menu_top(0),
70211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    menu_items(0),
71211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    menu_sel(0),
7232a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker
7332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    // These values are correct for the default image resources
7432a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    // provided with the android platform.  Devices which use
7532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    // different resources should have a subclass of ScreenRecoveryUI
7632a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    // that overrides Init() to set these values appropriately and
7732a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    // then call the superclass Init().
7832a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    animation_fps(20),
798347cb2d813b9a8b7c9165aadaea0b699eb5082fDoug Zongker    indeterminate_frames(6),
808347cb2d813b9a8b7c9165aadaea0b699eb5082fDoug Zongker    installing_frames(7),
818347cb2d813b9a8b7c9165aadaea0b699eb5082fDoug Zongker    install_overlay_offset_x(13),
828347cb2d813b9a8b7c9165aadaea0b699eb5082fDoug Zongker    install_overlay_offset_y(190),
8352eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    overlay_offset_x(-1),
8452eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    overlay_offset_y(-1) {
852f6877a0220475303907203308c018d789ea1a53yetta_wu
862f6877a0220475303907203308c018d789ea1a53yetta_wu    for (int i = 0; i < 5; i++)
872f6877a0220475303907203308c018d789ea1a53yetta_wu        backgroundIcon[i] = NULL;
882f6877a0220475303907203308c018d789ea1a53yetta_wu
8980a7a4642be31db7ecd5eaa9e62b78deaa461146Bjorn Andersson    memset(text, 0, sizeof(text));
9080a7a4642be31db7ecd5eaa9e62b78deaa461146Bjorn Andersson
91211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_init(&updateMutex, NULL);
92211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    self = this;
93211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker}
94211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
956809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// Draw the given frame over the installation overlay animation.  The
966809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// background is not cleared or draw with the base icon first; we
976809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// assume that the frame already contains some other frame of the
986809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// animation.  Does nothing if no overlay animation is defined.
99211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
100211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_install_overlay_locked(int frame) {
10152eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    if (installationOverlay == NULL || overlay_offset_x < 0) return;
102211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    gr_surface surface = installationOverlay[frame];
1036809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    int iconWidth = gr_get_width(surface);
1046809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    int iconHeight = gr_get_height(surface);
1056809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    gr_blit(surface, 0, 0, iconWidth, iconHeight,
10602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker            overlay_offset_x, overlay_offset_y);
1076809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker}
1086809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
109c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Clear the screen and draw the currently selected background icon (if any).
110211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
111211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_background_locked(Icon icon)
112c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
113211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pagesIdentical = false;
114c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_color(0, 0, 0, 255);
115c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_fill(0, 0, gr_fb_width(), gr_fb_height());
116c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
117c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (icon) {
118211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        gr_surface surface = backgroundIcon[icon];
11902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_surface text_surface = backgroundText[icon];
12002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
1216809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int iconWidth = gr_get_width(surface);
1226809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int iconHeight = gr_get_height(surface);
12302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textWidth = gr_get_width(text_surface);
12402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textHeight = gr_get_height(text_surface);
12502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
126c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        int iconX = (gr_fb_width() - iconWidth) / 2;
12702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int iconY = (gr_fb_height() - (iconHeight+textHeight+40)) / 2;
12802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
12902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textX = (gr_fb_width() - textWidth) / 2;
13002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textY = ((gr_fb_height() - (iconHeight+textHeight+40)) / 2) + iconHeight + 40;
13102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
1326809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
13302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        if (icon == INSTALLING_UPDATE || icon == ERASING) {
134211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            draw_install_overlay_locked(installingFrame);
1356809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        }
13602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
13702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_color(255, 255, 255, 255);
13802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_texticon(textX, textY, text_surface);
139c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
140c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
141c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
142c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Draw the progress bar (if any) on the screen.  Does not flip pages.
143211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
144211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_progress_locked()
145c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
14669f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    if (currentIcon == ERROR) return;
14769f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker
14802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
149211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        draw_install_overlay_locked(installingFrame);
1506809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    }
151c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
152211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType != EMPTY) {
15302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);
154211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        int width = gr_get_width(progressBarEmpty);
155211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        int height = gr_get_height(progressBarEmpty);
156c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1576809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int dx = (gr_fb_width() - width)/2;
1586809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
159c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1606809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // Erase behind the progress bar (in case this was a progress-only update)
1616809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        gr_color(0, 0, 0, 255);
1626809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        gr_fill(dx, dy, width, height);
163c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
164211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        if (progressBarType == DETERMINATE) {
165211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            float p = progressScopeStart + progress * progressScopeSize;
166211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            int pos = (int) (p * width);
167c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1685fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            if (rtl_locale) {
1695fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                // Fill the progress bar from right to left.
1705fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos > 0) {
1715fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarFill, width-pos, 0, pos, height, dx+width-pos, dy);
1725fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1735fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos < width-1) {
1745fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarEmpty, 0, 0, width-pos, height, dx, dy);
1755fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1765fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            } else {
1775fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                // Fill the progress bar from left to right.
1785fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos > 0) {
1795fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);
1805fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1815fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos < width-1) {
1825fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
1835fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1846809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            }
185c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
186c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
187211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        if (progressBarType == INDETERMINATE) {
1886809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            static int frame = 0;
189211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            gr_blit(progressBarIndeterminate[frame], 0, 0, width, height, dx, dy);
1905fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            // in RTL locales, we run the animation backwards, which
1915fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            // makes the spinner spin the other way.
1925fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            if (rtl_locale) {
1935fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                frame = (frame + indeterminate_frames - 1) % indeterminate_frames;
1945fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            } else {
1955fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                frame = (frame + 1) % indeterminate_frames;
1965fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            }
1976809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        }
198c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
199c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
200c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
2016fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker#define C_HEADER  247,0,6
2026fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker#define C_MENU    0,106,157
2036fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker#define C_LOG     249,194,0
204c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
205c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Redraw everything on the screen.  Does not flip pages.
206211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
207211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_screen_locked()
208c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
209211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    draw_background_locked(currentIcon);
210c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    draw_progress_locked();
211c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
212c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (show_text) {
213c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        gr_color(0, 0, 0, 160);
214c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        gr_fill(0, 0, gr_fb_width(), gr_fb_height());
215c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
2166fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        int y = 0;
217c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        int i = 0;
218c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (show_menu) {
2196fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_color(C_HEADER, 255);
220c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
221c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            for (; i < menu_top + menu_items; ++i) {
2226fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                if (i == menu_top) gr_color(C_MENU, 255);
2236fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker
224c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                if (i == menu_top + menu_sel) {
2256fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    // draw the highlight bar
2266fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    gr_fill(0, y-2, gr_fb_width(), y+char_height+2);
2276fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    // white text of selected item
228c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                    gr_color(255, 255, 255, 255);
2296fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    if (menu[i][0]) gr_text(4, y, menu[i], 1);
2306fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    gr_color(C_MENU, 255);
231c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                } else {
2326fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    if (menu[i][0]) gr_text(4, y, menu[i], i < menu_top);
233c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                }
2346fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                y += char_height+4;
235c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
2366fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_color(C_MENU, 255);
2376fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            y += 4;
2386fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_fill(0, y, gr_fb_width(), y+2);
2396fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            y += 4;
240c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            ++i;
241c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
242c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
2436fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        gr_color(C_LOG, 255);
2446fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker
2456fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // display from the bottom up, until we hit the top of the
2466fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // screen, the bottom of the menu, or we've displayed the
2476fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // entire text buffer.
2486fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        int ty;
2496fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        int row = (text_top+text_rows-1) % text_rows;
2506fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        for (int ty = gr_fb_height() - char_height, count = 0;
2516fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker             ty > y+2 && count < text_rows;
2526fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker             ty -= char_height, ++count) {
2536fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_text(4, ty, text[row], 0);
2546fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            --row;
2556fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            if (row < 0) row = text_rows-1;
256c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
257c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
258c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
259c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
260c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Redraw everything on the screen and flip the screen (make it visible).
261211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
262211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::update_screen_locked()
263c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
264c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    draw_screen_locked();
265c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_flip();
266c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
267c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
268c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Updates only the progress bar, if possible, otherwise redraws the screen.
269211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
270211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::update_progress_locked()
271c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
272211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (show_text || !pagesIdentical) {
273c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        draw_screen_locked();    // Must redraw the whole screen
274211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        pagesIdentical = true;
275c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    } else {
2766809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        draw_progress_locked();  // Draw only the progress bar and overlays
277c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
278c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_flip();
279c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
280c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
281c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Keeps the progress bar updated, even when the process is otherwise busy.
28232a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongkervoid* ScreenRecoveryUI::progress_thread(void *cookie) {
28332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    self->progress_loop();
28432a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    return NULL;
28532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker}
28632a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker
28732a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongkervoid ScreenRecoveryUI::progress_loop() {
28832a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    double interval = 1.0 / animation_fps;
289c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    for (;;) {
2906809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double start = now();
29132a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        pthread_mutex_lock(&updateMutex);
292c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
2936809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int redraw = 0;
2946809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
2956809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // update the installation animation, if active
2966809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // skip this if we have a text overlay (too expensive to update)
29702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) &&
29802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker            installing_frames > 0 && !show_text) {
29932a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker            installingFrame = (installingFrame + 1) % installing_frames;
3006809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            redraw = 1;
3016809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        }
3026809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
303c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // update the progress bar animation, if active
304c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // skip this if we have a text overlay (too expensive to update)
30532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        if (progressBarType == INDETERMINATE && !show_text) {
3066809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            redraw = 1;
307c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
308c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
309c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // move the progress bar forward on timed intervals, if configured
31032a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        int duration = progressScopeDuration;
31132a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        if (progressBarType == DETERMINATE && duration > 0) {
31232a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker            double elapsed = now() - progressScopeTime;
31369f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            float p = 1.0 * elapsed / duration;
31469f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            if (p > 1.0) p = 1.0;
31569f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            if (p > progress) {
31669f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker                progress = p;
3176809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker                redraw = 1;
318c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
319c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
320c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
32132a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        if (redraw) update_progress_locked();
3226809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
32332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        pthread_mutex_unlock(&updateMutex);
3246809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double end = now();
3256809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // minimum of 20ms delay between frames
3266809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double delay = interval - (end-start);
3276809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        if (delay < 0.02) delay = 0.02;
3286809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        usleep((long)(delay * 1000000));
329c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
330c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
331c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
332211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::LoadBitmap(const char* filename, gr_surface* surface) {
333211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    int result = res_create_surface(filename, surface);
334211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (result < 0) {
335211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
336211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    }
337211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker}
338211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
33902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongkervoid ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, gr_surface* surface) {
34002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    int result = res_create_localized_surface(filename, surface);
34102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    if (result < 0) {
34202ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
34302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    }
34402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker}
34502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
346211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::Init()
347c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
348c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_init();
349c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
35055a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker    gr_font_size(&char_width, &char_height);
35155a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker
352c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    text_col = text_row = 0;
35355a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker    text_rows = gr_fb_height() / char_height;
354211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (text_rows > kMaxRows) text_rows = kMaxRows;
355c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    text_top = 1;
356c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
35755a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker    text_cols = gr_fb_width() / char_width;
358211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
359211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
36002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);
36102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
362211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("icon_error", &backgroundIcon[ERROR]);
36302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
36402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
365211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("progress_empty", &progressBarEmpty);
366211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("progress_fill", &progressBarFill);
367c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
36802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
36902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
37002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
37102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
37202ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
373c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int i;
3746809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
37532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    progressBarIndeterminate = (gr_surface*)malloc(indeterminate_frames *
37628ce47cfa6919518a8c298088bf08b03bb374c0fDoug Zongker                                                    sizeof(gr_surface));
37732a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    for (i = 0; i < indeterminate_frames; ++i) {
3786809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        char filename[40];
379be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker        // "indeterminate01.png", "indeterminate02.png", ...
380be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker        sprintf(filename, "indeterminate%02d", i+1);
381211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        LoadBitmap(filename, progressBarIndeterminate+i);
3826809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    }
3836809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
38432a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    if (installing_frames > 0) {
38532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        installationOverlay = (gr_surface*)malloc(installing_frames *
38628ce47cfa6919518a8c298088bf08b03bb374c0fDoug Zongker                                                   sizeof(gr_surface));
38732a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        for (i = 0; i < installing_frames; ++i) {
3886809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            char filename[40];
389be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker            // "icon_installing_overlay01.png",
390be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker            // "icon_installing_overlay02.png", ...
391be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker            sprintf(filename, "icon_installing_overlay%02d", i+1);
392211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            LoadBitmap(filename, installationOverlay+i);
393c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
3946809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    } else {
395211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        installationOverlay = NULL;
396c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
397c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
398211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_create(&progress_t, NULL, progress_thread, NULL);
39932a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker
40032a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    RecoveryUI::Init();
401c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
402c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
4035fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongkervoid ScreenRecoveryUI::SetLocale(const char* locale) {
4045fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker    if (locale) {
4055fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        char* lang = strdup(locale);
4065fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        for (char* p = lang; *p; ++p) {
4075fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            if (*p == '_') {
4085fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                *p = '\0';
4095fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                break;
4105fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            }
4115fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        }
4125fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker
4135fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        // A bit cheesy: keep an explicit list of supported languages
4145fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        // that are RTL.
4155fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        if (strcmp(lang, "ar") == 0 ||   // Arabic
4165fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            strcmp(lang, "fa") == 0 ||   // Persian (Farsi)
4175fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            strcmp(lang, "he") == 0 ||   // Hebrew (new language code)
418b66cb69e3933d5f56f06d88cd31817f49d87df5fDoug Zongker            strcmp(lang, "iw") == 0 ||   // Hebrew (old language code)
419b66cb69e3933d5f56f06d88cd31817f49d87df5fDoug Zongker            strcmp(lang, "ur") == 0) {   // Urdu
4205fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            rtl_locale = true;
4215fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        }
4225fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        free(lang);
4235fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker    }
4245fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker}
4255fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker
426211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetBackground(Icon icon)
427c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
428211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
42902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
43002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    // Adjust the offset to account for the positioning of the
43102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    // base image on the screen.
43202ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    if (backgroundIcon[icon] != NULL) {
43302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_surface bg = backgroundIcon[icon];
43402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_surface text = backgroundText[icon];
43502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        overlay_offset_x = install_overlay_offset_x + (gr_fb_width() - gr_get_width(bg)) / 2;
43602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        overlay_offset_y = install_overlay_offset_y +
43702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker            (gr_fb_height() - (gr_get_height(bg) + gr_get_height(text) + 40)) / 2;
43802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    }
43902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
44052eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    currentIcon = icon;
44152eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    update_screen_locked();
44252eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker
443211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
444c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
445c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
446211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetProgressType(ProgressType type)
447c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
448211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
449211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType != type) {
450211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        progressBarType = type;
451c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_progress_locked();
452c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
45369f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    progressScopeStart = 0;
45469f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    progress = 0;
455211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
456c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
457c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
458211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::ShowProgress(float portion, float seconds)
459c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
460211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
461211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressBarType = DETERMINATE;
462211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeStart += progressScopeSize;
463211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeSize = portion;
464211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeTime = now();
465211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeDuration = seconds;
466211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progress = 0;
467c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    update_progress_locked();
468211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
469c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
470c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
471211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetProgress(float fraction)
472c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
473211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
474c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (fraction < 0.0) fraction = 0.0;
475c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (fraction > 1.0) fraction = 1.0;
476211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType == DETERMINATE && fraction > progress) {
477c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // Skip updates that aren't visibly different.
478211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        int width = gr_get_width(progressBarIndeterminate[0]);
479211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        float scale = width * progressScopeSize;
480211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        if ((int) (progress * scale) != (int) (fraction * scale)) {
481211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            progress = fraction;
482c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            update_progress_locked();
483c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
484c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
485211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
486c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
487c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
488211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::Print(const char *fmt, ...)
489c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
490c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    char buf[256];
491c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_list ap;
492c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_start(ap, fmt);
493c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    vsnprintf(buf, 256, fmt, ap);
494c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_end(ap);
495c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
4963d177d055c9cf3571e4b7c098818b454d1dbf9d7Doug Zongker    fputs(buf, stdout);
497c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
498c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    // This can get called before ui_init(), so be careful.
499211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
500c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (text_rows > 0 && text_cols > 0) {
501c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        char *ptr;
502c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (ptr = buf; *ptr != '\0'; ++ptr) {
503c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (*ptr == '\n' || text_col >= text_cols) {
504c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text[text_row][text_col] = '\0';
505c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text_col = 0;
506c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text_row = (text_row + 1) % text_rows;
507c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                if (text_row == text_top) text_top = (text_top + 1) % text_rows;
508c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
509c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (*ptr != '\n') text[text_row][text_col++] = *ptr;
510c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
511c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        text[text_row][text_col] = '\0';
512c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
513c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
514211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
515c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
516c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
517211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::StartMenu(const char* const * headers, const char* const * items,
518211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker                                 int initial_selection) {
519c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int i;
520211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
521c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (text_rows > 0 && text_cols > 0) {
522c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (i = 0; i < text_rows; ++i) {
523c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (headers[i] == NULL) break;
524c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            strncpy(menu[i], headers[i], text_cols-1);
525c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            menu[i][text_cols-1] = '\0';
526c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
527c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_top = i;
528c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (; i < text_rows; ++i) {
529c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (items[i-menu_top] == NULL) break;
530c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            strncpy(menu[i], items[i-menu_top], text_cols-1);
531c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            menu[i][text_cols-1] = '\0';
532c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
533c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_items = i - menu_top;
534c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        show_menu = 1;
535be598881d079511385a88b12b7a14b97e63dc85eDoug Zongker        menu_sel = initial_selection;
536c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
537c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
538211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
539c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
540c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
541211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerint ScreenRecoveryUI::SelectMenu(int sel) {
542c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int old_sel;
543211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
544c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (show_menu > 0) {
545c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        old_sel = menu_sel;
546c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_sel = sel;
547c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel < 0) menu_sel = 0;
548c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel >= menu_items) menu_sel = menu_items-1;
549c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        sel = menu_sel;
550c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel != old_sel) update_screen_locked();
551c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
552211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
553c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    return sel;
554c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
555c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
556211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::EndMenu() {
557c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int i;
558211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
559c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (show_menu > 0 && text_rows > 0 && text_cols > 0) {
560c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        show_menu = 0;
561c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
562c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
563211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
564c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
565c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
566211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerbool ScreenRecoveryUI::IsTextVisible()
567c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
568211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
569c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int visible = show_text;
570211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
571c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    return visible;
572c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
573c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
574211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerbool ScreenRecoveryUI::WasTextEverVisible()
5755cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker{
576211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
5775cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    int ever_visible = show_text_ever;
578211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
5795cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    return ever_visible;
5805cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker}
5815cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker
582211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::ShowText(bool visible)
5834bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker{
584211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
5854bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker    show_text = visible;
5865cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    if (show_text) show_text_ever = 1;
5874bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker    update_screen_locked();
588211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
5894bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker}
590