screen_ui.cpp revision 2f6877a0220475303907203308c018d789ea1a53
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
89211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_init(&updateMutex, NULL);
90211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    self = this;
91211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker}
92211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
936809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// Draw the given frame over the installation overlay animation.  The
946809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// background is not cleared or draw with the base icon first; we
956809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// assume that the frame already contains some other frame of the
966809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker// animation.  Does nothing if no overlay animation is defined.
97211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
98211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_install_overlay_locked(int frame) {
9952eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    if (installationOverlay == NULL || overlay_offset_x < 0) return;
100211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    gr_surface surface = installationOverlay[frame];
1016809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    int iconWidth = gr_get_width(surface);
1026809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    int iconHeight = gr_get_height(surface);
1036809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    gr_blit(surface, 0, 0, iconWidth, iconHeight,
10402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker            overlay_offset_x, overlay_offset_y);
1056809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker}
1066809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
107c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Clear the screen and draw the currently selected background icon (if any).
108211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
109211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_background_locked(Icon icon)
110c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
111211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pagesIdentical = false;
112c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_color(0, 0, 0, 255);
113c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_fill(0, 0, gr_fb_width(), gr_fb_height());
114c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
115c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (icon) {
116211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        gr_surface surface = backgroundIcon[icon];
11702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_surface text_surface = backgroundText[icon];
11802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
1196809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int iconWidth = gr_get_width(surface);
1206809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int iconHeight = gr_get_height(surface);
12102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textWidth = gr_get_width(text_surface);
12202ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textHeight = gr_get_height(text_surface);
12302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
124c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        int iconX = (gr_fb_width() - iconWidth) / 2;
12502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int iconY = (gr_fb_height() - (iconHeight+textHeight+40)) / 2;
12602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
12702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textX = (gr_fb_width() - textWidth) / 2;
12802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textY = ((gr_fb_height() - (iconHeight+textHeight+40)) / 2) + iconHeight + 40;
12902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
1306809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
13102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        if (icon == INSTALLING_UPDATE || icon == ERASING) {
132211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            draw_install_overlay_locked(installingFrame);
1336809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        }
13402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
13502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_color(255, 255, 255, 255);
13602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_texticon(textX, textY, text_surface);
137c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
138c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
139c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
140c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Draw the progress bar (if any) on the screen.  Does not flip pages.
141211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
142211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_progress_locked()
143c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
14469f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    if (currentIcon == ERROR) return;
14569f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker
14602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
147211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        draw_install_overlay_locked(installingFrame);
1486809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    }
149c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
150211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType != EMPTY) {
15102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);
152211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        int width = gr_get_width(progressBarEmpty);
153211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        int height = gr_get_height(progressBarEmpty);
154c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1556809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int dx = (gr_fb_width() - width)/2;
1566809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
157c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1586809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // Erase behind the progress bar (in case this was a progress-only update)
1596809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        gr_color(0, 0, 0, 255);
1606809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        gr_fill(dx, dy, width, height);
161c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
162211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        if (progressBarType == DETERMINATE) {
163211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            float p = progressScopeStart + progress * progressScopeSize;
164211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            int pos = (int) (p * width);
165c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1665fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            if (rtl_locale) {
1675fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                // Fill the progress bar from right to left.
1685fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos > 0) {
1695fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarFill, width-pos, 0, pos, height, dx+width-pos, dy);
1705fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1715fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos < width-1) {
1725fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarEmpty, 0, 0, width-pos, height, dx, dy);
1735fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1745fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            } else {
1755fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                // Fill the progress bar from left to right.
1765fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos > 0) {
1775fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);
1785fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1795fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos < width-1) {
1805fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
1815fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1826809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            }
183c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
184c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
185211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        if (progressBarType == INDETERMINATE) {
1866809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            static int frame = 0;
187211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            gr_blit(progressBarIndeterminate[frame], 0, 0, width, height, dx, dy);
1885fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            // in RTL locales, we run the animation backwards, which
1895fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            // makes the spinner spin the other way.
1905fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            if (rtl_locale) {
1915fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                frame = (frame + indeterminate_frames - 1) % indeterminate_frames;
1925fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            } else {
1935fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                frame = (frame + 1) % indeterminate_frames;
1945fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            }
1956809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        }
196c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
197c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
198c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1996fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker#define C_HEADER  247,0,6
2006fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker#define C_MENU    0,106,157
2016fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker#define C_LOG     249,194,0
202c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
203c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Redraw everything on the screen.  Does not flip pages.
204211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
205211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_screen_locked()
206c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
207211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    draw_background_locked(currentIcon);
208c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    draw_progress_locked();
209c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
210c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (show_text) {
211c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        gr_color(0, 0, 0, 160);
212c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        gr_fill(0, 0, gr_fb_width(), gr_fb_height());
213c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
2146fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        int y = 0;
215c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        int i = 0;
216c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (show_menu) {
2176fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_color(C_HEADER, 255);
218c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
219c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            for (; i < menu_top + menu_items; ++i) {
2206fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                if (i == menu_top) gr_color(C_MENU, 255);
2216fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker
222c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                if (i == menu_top + menu_sel) {
2236fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    // draw the highlight bar
2246fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    gr_fill(0, y-2, gr_fb_width(), y+char_height+2);
2256fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    // white text of selected item
226c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                    gr_color(255, 255, 255, 255);
2276fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    if (menu[i][0]) gr_text(4, y, menu[i], 1);
2286fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    gr_color(C_MENU, 255);
229c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                } else {
2306fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    if (menu[i][0]) gr_text(4, y, menu[i], i < menu_top);
231c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                }
2326fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                y += char_height+4;
233c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
2346fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_color(C_MENU, 255);
2356fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            y += 4;
2366fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_fill(0, y, gr_fb_width(), y+2);
2376fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            y += 4;
238c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            ++i;
239c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
240c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
2416fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        gr_color(C_LOG, 255);
2426fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker
2436fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // display from the bottom up, until we hit the top of the
2446fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // screen, the bottom of the menu, or we've displayed the
2456fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // entire text buffer.
2466fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        int ty;
2476fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        int row = (text_top+text_rows-1) % text_rows;
2486fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        for (int ty = gr_fb_height() - char_height, count = 0;
2496fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker             ty > y+2 && count < text_rows;
2506fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker             ty -= char_height, ++count) {
2516fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_text(4, ty, text[row], 0);
2526fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            --row;
2536fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            if (row < 0) row = text_rows-1;
254c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
255c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
256c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
257c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
258c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Redraw everything on the screen and flip the screen (make it visible).
259211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
260211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::update_screen_locked()
261c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
262c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    draw_screen_locked();
263c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_flip();
264c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
265c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
266c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Updates only the progress bar, if possible, otherwise redraws the screen.
267211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
268211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::update_progress_locked()
269c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
270211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (show_text || !pagesIdentical) {
271c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        draw_screen_locked();    // Must redraw the whole screen
272211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        pagesIdentical = true;
273c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    } else {
2746809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        draw_progress_locked();  // Draw only the progress bar and overlays
275c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
276c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_flip();
277c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
278c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
279c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Keeps the progress bar updated, even when the process is otherwise busy.
28032a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongkervoid* ScreenRecoveryUI::progress_thread(void *cookie) {
28132a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    self->progress_loop();
28232a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    return NULL;
28332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker}
28432a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker
28532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongkervoid ScreenRecoveryUI::progress_loop() {
28632a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    double interval = 1.0 / animation_fps;
287c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    for (;;) {
2886809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double start = now();
28932a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        pthread_mutex_lock(&updateMutex);
290c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
2916809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int redraw = 0;
2926809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
2936809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // update the installation animation, if active
2946809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // skip this if we have a text overlay (too expensive to update)
29502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) &&
29602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker            installing_frames > 0 && !show_text) {
29732a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker            installingFrame = (installingFrame + 1) % installing_frames;
2986809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            redraw = 1;
2996809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        }
3006809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
301c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // update the progress bar animation, if active
302c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // skip this if we have a text overlay (too expensive to update)
30332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        if (progressBarType == INDETERMINATE && !show_text) {
3046809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            redraw = 1;
305c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
306c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
307c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // move the progress bar forward on timed intervals, if configured
30832a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        int duration = progressScopeDuration;
30932a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        if (progressBarType == DETERMINATE && duration > 0) {
31032a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker            double elapsed = now() - progressScopeTime;
31169f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            float p = 1.0 * elapsed / duration;
31269f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            if (p > 1.0) p = 1.0;
31369f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            if (p > progress) {
31469f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker                progress = p;
3156809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker                redraw = 1;
316c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
317c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
318c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
31932a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        if (redraw) update_progress_locked();
3206809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
32132a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        pthread_mutex_unlock(&updateMutex);
3226809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double end = now();
3236809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // minimum of 20ms delay between frames
3246809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double delay = interval - (end-start);
3256809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        if (delay < 0.02) delay = 0.02;
3266809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        usleep((long)(delay * 1000000));
327c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
328c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
329c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
330211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::LoadBitmap(const char* filename, gr_surface* surface) {
331211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    int result = res_create_surface(filename, surface);
332211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (result < 0) {
333211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
334211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    }
335211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker}
336211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
33702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongkervoid ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, gr_surface* surface) {
33802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    int result = res_create_localized_surface(filename, surface);
33902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    if (result < 0) {
34002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
34102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    }
34202ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker}
34302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
344211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::Init()
345c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
346c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_init();
347c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
34855a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker    gr_font_size(&char_width, &char_height);
34955a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker
350c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    text_col = text_row = 0;
35155a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker    text_rows = gr_fb_height() / char_height;
352211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (text_rows > kMaxRows) text_rows = kMaxRows;
353c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    text_top = 1;
354c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
35555a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker    text_cols = gr_fb_width() / char_width;
356211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
357211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
35802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadBitmap("icon_installing", &backgroundIcon[INSTALLING_UPDATE]);
35902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
360211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("icon_error", &backgroundIcon[ERROR]);
36102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
36202ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
363211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("progress_empty", &progressBarEmpty);
364211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("progress_fill", &progressBarFill);
365c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
36602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
36702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
36802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
36902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
37002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
371c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int i;
3726809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
37332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    progressBarIndeterminate = (gr_surface*)malloc(indeterminate_frames *
37428ce47cfa6919518a8c298088bf08b03bb374c0fDoug Zongker                                                    sizeof(gr_surface));
37532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    for (i = 0; i < indeterminate_frames; ++i) {
3766809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        char filename[40];
377be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker        // "indeterminate01.png", "indeterminate02.png", ...
378be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker        sprintf(filename, "indeterminate%02d", i+1);
379211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        LoadBitmap(filename, progressBarIndeterminate+i);
3806809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    }
3816809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
38232a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    if (installing_frames > 0) {
38332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        installationOverlay = (gr_surface*)malloc(installing_frames *
38428ce47cfa6919518a8c298088bf08b03bb374c0fDoug Zongker                                                   sizeof(gr_surface));
38532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        for (i = 0; i < installing_frames; ++i) {
3866809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            char filename[40];
387be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker            // "icon_installing_overlay01.png",
388be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker            // "icon_installing_overlay02.png", ...
389be6d4d10529860037c165e4441a2d23f539e7b00Doug Zongker            sprintf(filename, "icon_installing_overlay%02d", i+1);
390211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            LoadBitmap(filename, installationOverlay+i);
391c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
3926809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    } else {
393211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        installationOverlay = NULL;
394c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
395c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
396211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_create(&progress_t, NULL, progress_thread, NULL);
39732a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker
39832a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    RecoveryUI::Init();
399c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
400c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
4015fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongkervoid ScreenRecoveryUI::SetLocale(const char* locale) {
4025fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker    if (locale) {
4035fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        char* lang = strdup(locale);
4045fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        for (char* p = lang; *p; ++p) {
4055fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            if (*p == '_') {
4065fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                *p = '\0';
4075fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                break;
4085fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            }
4095fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        }
4105fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker
4115fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        // A bit cheesy: keep an explicit list of supported languages
4125fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        // that are RTL.
4135fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        if (strcmp(lang, "ar") == 0 ||   // Arabic
4145fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            strcmp(lang, "fa") == 0 ||   // Persian (Farsi)
4155fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            strcmp(lang, "he") == 0 ||   // Hebrew (new language code)
416b66cb69e3933d5f56f06d88cd31817f49d87df5fDoug Zongker            strcmp(lang, "iw") == 0 ||   // Hebrew (old language code)
417b66cb69e3933d5f56f06d88cd31817f49d87df5fDoug Zongker            strcmp(lang, "ur") == 0) {   // Urdu
4185fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            rtl_locale = true;
4195fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        }
4205fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        free(lang);
4215fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker    }
4225fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker}
4235fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker
424211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetBackground(Icon icon)
425c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
426211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
42702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
42802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    // Adjust the offset to account for the positioning of the
42902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    // base image on the screen.
43002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    if (backgroundIcon[icon] != NULL) {
43102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_surface bg = backgroundIcon[icon];
43202ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_surface text = backgroundText[icon];
43302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        overlay_offset_x = install_overlay_offset_x + (gr_fb_width() - gr_get_width(bg)) / 2;
43402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        overlay_offset_y = install_overlay_offset_y +
43502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker            (gr_fb_height() - (gr_get_height(bg) + gr_get_height(text) + 40)) / 2;
43602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    }
43702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
43852eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    currentIcon = icon;
43952eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    update_screen_locked();
44052eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker
441211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
442c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
443c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
444211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetProgressType(ProgressType type)
445c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
446211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
447211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType != type) {
448211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        progressBarType = type;
449c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_progress_locked();
450c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
45169f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    progressScopeStart = 0;
45269f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    progress = 0;
453211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
454c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
455c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
456211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::ShowProgress(float portion, float seconds)
457c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
458211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
459211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressBarType = DETERMINATE;
460211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeStart += progressScopeSize;
461211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeSize = portion;
462211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeTime = now();
463211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeDuration = seconds;
464211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progress = 0;
465c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    update_progress_locked();
466211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
467c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
468c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
469211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetProgress(float fraction)
470c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
471211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
472c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (fraction < 0.0) fraction = 0.0;
473c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (fraction > 1.0) fraction = 1.0;
474211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType == DETERMINATE && fraction > progress) {
475c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // Skip updates that aren't visibly different.
476211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        int width = gr_get_width(progressBarIndeterminate[0]);
477211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        float scale = width * progressScopeSize;
478211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        if ((int) (progress * scale) != (int) (fraction * scale)) {
479211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            progress = fraction;
480c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            update_progress_locked();
481c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
482c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
483211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
484c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
485c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
486211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::Print(const char *fmt, ...)
487c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
488c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    char buf[256];
489c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_list ap;
490c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_start(ap, fmt);
491c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    vsnprintf(buf, 256, fmt, ap);
492c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_end(ap);
493c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
4943d177d055c9cf3571e4b7c098818b454d1dbf9d7Doug Zongker    fputs(buf, stdout);
495c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
496c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    // This can get called before ui_init(), so be careful.
497211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
498c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (text_rows > 0 && text_cols > 0) {
499c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        char *ptr;
500c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (ptr = buf; *ptr != '\0'; ++ptr) {
501c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (*ptr == '\n' || text_col >= text_cols) {
502c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text[text_row][text_col] = '\0';
503c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text_col = 0;
504c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text_row = (text_row + 1) % text_rows;
505c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                if (text_row == text_top) text_top = (text_top + 1) % text_rows;
506c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
507c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (*ptr != '\n') text[text_row][text_col++] = *ptr;
508c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
509c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        text[text_row][text_col] = '\0';
510c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
511c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
512211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
513c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
514c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
515211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::StartMenu(const char* const * headers, const char* const * items,
516211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker                                 int initial_selection) {
517c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int i;
518211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
519c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (text_rows > 0 && text_cols > 0) {
520c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (i = 0; i < text_rows; ++i) {
521c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (headers[i] == NULL) break;
522c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            strncpy(menu[i], headers[i], text_cols-1);
523c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            menu[i][text_cols-1] = '\0';
524c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
525c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_top = i;
526c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (; i < text_rows; ++i) {
527c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (items[i-menu_top] == NULL) break;
528c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            strncpy(menu[i], items[i-menu_top], text_cols-1);
529c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            menu[i][text_cols-1] = '\0';
530c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
531c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_items = i - menu_top;
532c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        show_menu = 1;
533be598881d079511385a88b12b7a14b97e63dc85eDoug Zongker        menu_sel = initial_selection;
534c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
535c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
536211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
537c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
538c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
539211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerint ScreenRecoveryUI::SelectMenu(int sel) {
540c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int old_sel;
541211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
542c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (show_menu > 0) {
543c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        old_sel = menu_sel;
544c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_sel = sel;
545c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel < 0) menu_sel = 0;
546c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel >= menu_items) menu_sel = menu_items-1;
547c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        sel = menu_sel;
548c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel != old_sel) update_screen_locked();
549c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
550211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
551c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    return sel;
552c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
553c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
554211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::EndMenu() {
555c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int i;
556211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
557c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (show_menu > 0 && text_rows > 0 && text_cols > 0) {
558c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        show_menu = 0;
559c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
560c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
561211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
562c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
563c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
564211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerbool ScreenRecoveryUI::IsTextVisible()
565c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
566211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
567c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int visible = show_text;
568211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
569c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    return visible;
570c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
571c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
572211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerbool ScreenRecoveryUI::WasTextEverVisible()
5735cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker{
574211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
5755cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    int ever_visible = show_text_ever;
576211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
5775cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    return ever_visible;
5785cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker}
5795cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker
580211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::ShowText(bool visible)
5814bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker{
582211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
5834bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker    show_text = visible;
5845cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    if (show_text) show_text_ever = 1;
5854bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker    update_screen_locked();
586211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
5874bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker}
588