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),
55a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongker    locale(NULL),
565fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker    rtl_locale(false),
57211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressBarType(EMPTY),
58211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeStart(0),
59211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeSize(0),
60211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progress(0),
61211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pagesIdentical(false),
62211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_cols(0),
63211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_rows(0),
64211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_col(0),
65211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_row(0),
66211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    text_top(0),
67211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    show_text(false),
68211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    show_text_ever(false),
69211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    show_menu(false),
70211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    menu_top(0),
71211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    menu_items(0),
72211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    menu_sel(0),
7332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    animation_fps(20),
74eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker    installing_frames(-1),
75c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker    stage(-1),
76c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker    max_stage(-1) {
775b468fc9305bf3adef681fa1e56364fc51761af8yetta_wu
785b468fc9305bf3adef681fa1e56364fc51761af8yetta_wu    for (int i = 0; i < 5; i++)
795b468fc9305bf3adef681fa1e56364fc51761af8yetta_wu        backgroundIcon[i] = NULL;
805b468fc9305bf3adef681fa1e56364fc51761af8yetta_wu
8180a7a4642be31db7ecd5eaa9e62b78deaa461146Bjorn Andersson    memset(text, 0, sizeof(text));
8280a7a4642be31db7ecd5eaa9e62b78deaa461146Bjorn Andersson
83211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_init(&updateMutex, NULL);
84211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    self = this;
85211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker}
86211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
87c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Clear the screen and draw the currently selected background icon (if any).
88211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
89211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_background_locked(Icon icon)
90c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
91211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pagesIdentical = false;
925b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker    gr_color(0, 0, 0, 255);
9339cf417e17011a72dd39acfe4cc8c90af26bdbafDoug Zongker    gr_clear();
94c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
95c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (icon) {
96211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        gr_surface surface = backgroundIcon[icon];
97eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker        if (icon == INSTALLING_UPDATE || icon == ERASING) {
98eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker            surface = installation[installingFrame];
99eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker        }
10002ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_surface text_surface = backgroundText[icon];
10102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
1026809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int iconWidth = gr_get_width(surface);
1036809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int iconHeight = gr_get_height(surface);
10402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textWidth = gr_get_width(text_surface);
10502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textHeight = gr_get_height(text_surface);
106c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker        int stageHeight = gr_get_height(stageMarkerEmpty);
107c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker
108c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker        int sh = (max_stage >= 0) ? stageHeight : 0;
10902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
110eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker        iconX = (gr_fb_width() - iconWidth) / 2;
111eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker        iconY = (gr_fb_height() - (iconHeight+textHeight+40+sh)) / 2;
11202ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
11302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int textX = (gr_fb_width() - textWidth) / 2;
114c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker        int textY = ((gr_fb_height() - (iconHeight+textHeight+40+sh)) / 2) + iconHeight + 40;
11502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
1166809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
117c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker        if (stageHeight > 0) {
118c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker            int sw = gr_get_width(stageMarkerEmpty);
119c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker            int x = (gr_fb_width() - max_stage * gr_get_width(stageMarkerEmpty)) / 2;
120c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker            int y = iconY + iconHeight + 20;
121c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker            for (int i = 0; i < max_stage; ++i) {
122c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker                gr_blit((i < stage) ? stageMarkerFill : stageMarkerEmpty,
123c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker                        0, 0, sw, stageHeight, x, y);
124c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker                x += sw;
125c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker            }
126c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker        }
127c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker
1285b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker        gr_color(255, 255, 255, 255);
12902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        gr_texticon(textX, textY, text_surface);
130c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
131c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
132c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
133c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Draw the progress bar (if any) on the screen.  Does not flip pages.
134211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
135211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::draw_progress_locked()
136c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
13769f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    if (currentIcon == ERROR) return;
13869f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker
13902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
140eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker        gr_surface icon = installation[installingFrame];
141eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker        gr_blit(icon, 0, 0, gr_get_width(icon), gr_get_height(icon), iconX, iconY);
1426809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker    }
143c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
144211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType != EMPTY) {
14502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        int iconHeight = gr_get_height(backgroundIcon[INSTALLING_UPDATE]);
146211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        int width = gr_get_width(progressBarEmpty);
147211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        int height = gr_get_height(progressBarEmpty);
148c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1496809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int dx = (gr_fb_width() - width)/2;
1506809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
151c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1526809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // Erase behind the progress bar (in case this was a progress-only update)
1535b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker        gr_color(0, 0, 0, 255);
1546809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        gr_fill(dx, dy, width, height);
155c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
156211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        if (progressBarType == DETERMINATE) {
157211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            float p = progressScopeStart + progress * progressScopeSize;
158211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            int pos = (int) (p * width);
159c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
1605fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            if (rtl_locale) {
1615fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                // Fill the progress bar from right to left.
1625fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos > 0) {
1635fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarFill, width-pos, 0, pos, height, dx+width-pos, dy);
1645fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1655fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos < width-1) {
1665fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarEmpty, 0, 0, width-pos, height, dx, dy);
1675fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1685fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            } else {
1695fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                // Fill the progress bar from left to right.
1705fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos > 0) {
1715fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarFill, 0, 0, pos, height, dx, dy);
1725fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1735fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                if (pos < width-1) {
1745fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                    gr_blit(progressBarEmpty, pos, 0, width-pos, height, dx+pos, dy);
1755fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                }
1766809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            }
177c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
178c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
179c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
180c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
181c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongkervoid ScreenRecoveryUI::SetColor(UIElement e) {
182c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker    switch (e) {
183c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker        case HEADER:
1845b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker            gr_color(247, 0, 6, 255);
185c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            break;
186c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker        case MENU:
187c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker        case MENU_SEL_BG:
1885b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker            gr_color(0, 106, 157, 255);
189c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            break;
190c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker        case MENU_SEL_FG:
191c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            gr_color(255, 255, 255, 255);
192c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            break;
193c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker        case LOG:
1945b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker            gr_color(249, 194, 0, 255);
1955b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker            break;
1965b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker        case TEXT_FILL:
1975b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker            gr_color(0, 0, 0, 160);
198c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            break;
199c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker        default:
200c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            gr_color(255, 255, 255, 255);
201c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            break;
202c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker    }
203c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker}
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{
20939cf417e17011a72dd39acfe4cc8c90af26bdbafDoug Zongker    if (!show_text) {
21039cf417e17011a72dd39acfe4cc8c90af26bdbafDoug Zongker        draw_background_locked(currentIcon);
21139cf417e17011a72dd39acfe4cc8c90af26bdbafDoug Zongker        draw_progress_locked();
21239cf417e17011a72dd39acfe4cc8c90af26bdbafDoug Zongker    } else {
2135b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker        gr_color(0, 0, 0, 255);
21439cf417e17011a72dd39acfe4cc8c90af26bdbafDoug Zongker        gr_clear();
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) {
219c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            SetColor(HEADER);
220c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
221c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            for (; i < menu_top + menu_items; ++i) {
222c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker                if (i == menu_top) SetColor(MENU);
2236fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker
224c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                if (i == menu_top + menu_sel) {
2256fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    // draw the highlight bar
226c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker                    SetColor(MENU_SEL_BG);
2275b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker                    gr_fill(0, y-2, gr_fb_width(), y+char_height+2);
2286fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                    // white text of selected item
229c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker                    SetColor(MENU_SEL_FG);
2305b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker                    if (menu[i][0]) gr_text(4, y, menu[i], 1);
231c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker                    SetColor(MENU);
232c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                } else {
2335b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker                    if (menu[i][0]) gr_text(4, y, menu[i], i < menu_top);
234c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                }
2356fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker                y += char_height+4;
236c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
237c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker            SetColor(MENU);
2386fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            y += 4;
2396fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            gr_fill(0, y, gr_fb_width(), y+2);
2406fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            y += 4;
241c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            ++i;
242c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
243c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
244c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker        SetColor(LOG);
2456fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker
2466fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // display from the bottom up, until we hit the top of the
2476fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // screen, the bottom of the menu, or we've displayed the
2486fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        // entire text buffer.
2496fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        int ty;
2506fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        int row = (text_top+text_rows-1) % text_rows;
2516fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker        for (int ty = gr_fb_height() - char_height, count = 0;
2526fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker             ty > y+2 && count < text_rows;
2536fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker             ty -= char_height, ++count) {
2545b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker            gr_text(4, ty, text[row], 0);
2556fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            --row;
2566fd59ac07d91eb373f4269a40e688aa82a6ccc6eDoug Zongker            if (row < 0) row = text_rows-1;
257c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
258c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
259c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
260c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
261c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Redraw everything on the screen and flip the screen (make it visible).
262211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
263211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::update_screen_locked()
264c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
265c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    draw_screen_locked();
266c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_flip();
267c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
268c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
269c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Updates only the progress bar, if possible, otherwise redraws the screen.
270211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker// Should only be called with updateMutex locked.
271211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::update_progress_locked()
272c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
273211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (show_text || !pagesIdentical) {
274c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        draw_screen_locked();    // Must redraw the whole screen
275211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        pagesIdentical = true;
276c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    } else {
2776809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        draw_progress_locked();  // Draw only the progress bar and overlays
278c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
279c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_flip();
280c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
281c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
282c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project// Keeps the progress bar updated, even when the process is otherwise busy.
28332a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongkervoid* ScreenRecoveryUI::progress_thread(void *cookie) {
28432a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    self->progress_loop();
28532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    return NULL;
28632a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker}
28732a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker
28832a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongkervoid ScreenRecoveryUI::progress_loop() {
28932a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    double interval = 1.0 / animation_fps;
290c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    for (;;) {
2916809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double start = now();
29232a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        pthread_mutex_lock(&updateMutex);
293c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
2946809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        int redraw = 0;
2956809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
2966809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // update the installation animation, if active
2976809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // skip this if we have a text overlay (too expensive to update)
29802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) &&
29902ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker            installing_frames > 0 && !show_text) {
30032a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker            installingFrame = (installingFrame + 1) % installing_frames;
3016809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker            redraw = 1;
3026809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        }
3036809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
304c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // move the progress bar forward on timed intervals, if configured
30532a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        int duration = progressScopeDuration;
30632a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        if (progressBarType == DETERMINATE && duration > 0) {
30732a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker            double elapsed = now() - progressScopeTime;
30869f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            float p = 1.0 * elapsed / duration;
30969f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            if (p > 1.0) p = 1.0;
31069f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker            if (p > progress) {
31169f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker                progress = p;
3126809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker                redraw = 1;
313c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
314c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
315c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
31632a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        if (redraw) update_progress_locked();
3176809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker
31832a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker        pthread_mutex_unlock(&updateMutex);
3196809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double end = now();
3206809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        // minimum of 20ms delay between frames
3216809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        double delay = interval - (end-start);
3226809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        if (delay < 0.02) delay = 0.02;
3236809c51f8db86f1ab00a076cf570439d11920d3aDoug Zongker        usleep((long)(delay * 1000000));
324c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
325c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
326c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
327211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::LoadBitmap(const char* filename, gr_surface* surface) {
328a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongker    int result = res_create_display_surface(filename, surface);
329211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (result < 0) {
330211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
331211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    }
332211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker}
333211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
334eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongkervoid ScreenRecoveryUI::LoadBitmapArray(const char* filename, int* frames, gr_surface** surface) {
335a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongker    int result = res_create_multi_display_surface(filename, frames, surface);
336eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker    if (result < 0) {
337eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
338eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker    }
339eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker}
340eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker
34102ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongkervoid ScreenRecoveryUI::LoadLocalizedBitmap(const char* filename, gr_surface* surface) {
342a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongker    int result = res_create_localized_alpha_surface(filename, locale, surface);
34302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    if (result < 0) {
34402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker        LOGE("missing bitmap %s\n(Code %d)\n", filename, result);
34502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    }
34602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker}
34702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
348211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::Init()
349c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
350c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    gr_init();
351c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
35255a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker    gr_font_size(&char_width, &char_height);
35355a36ac1e01205f2cd461cd2f89d92e3b64cddd2Doug Zongker
354c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    text_col = text_row = 0;
3555b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker    text_rows = gr_fb_height() / char_height;
356211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (text_rows > kMaxRows) text_rows = kMaxRows;
357c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    text_top = 1;
358c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
3595b5f6c2fd32839227d10ee3c97e662a415b80e2bDoug Zongker    text_cols = gr_fb_width() / char_width;
360211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (text_cols > kMaxCols - 1) text_cols = kMaxCols - 1;
361211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker
3629b8ae8038be65c2ec236bc04590716fbcd5363f6Alistair Strachan    backgroundIcon[NONE] = NULL;
363eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker    LoadBitmapArray("icon_installing", &installing_frames, &installation);
364eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker    backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[0] : NULL;
36502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
366211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("icon_error", &backgroundIcon[ERROR]);
36702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
36802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
369211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("progress_empty", &progressBarEmpty);
370211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    LoadBitmap("progress_fill", &progressBarFill);
371c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker    LoadBitmap("stage_empty", &stageMarkerEmpty);
372c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker    LoadBitmap("stage_fill", &stageMarkerFill);
373c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
37402ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
37502ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
37602ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
37702ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker    LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
37802ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
379211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_create(&progress_t, NULL, progress_thread, NULL);
38032a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker
38132a0a47a596509792fde8cdbf8b4b0705708b2beDoug Zongker    RecoveryUI::Init();
382c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
383c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
384a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongkervoid ScreenRecoveryUI::SetLocale(const char* new_locale) {
385a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongker    if (new_locale) {
386a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongker        this->locale = new_locale;
3875fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        char* lang = strdup(locale);
3885fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        for (char* p = lang; *p; ++p) {
3895fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            if (*p == '_') {
3905fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                *p = '\0';
3915fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker                break;
3925fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            }
3935fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        }
3945fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker
3955fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        // A bit cheesy: keep an explicit list of supported languages
3965fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        // that are RTL.
3975fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        if (strcmp(lang, "ar") == 0 ||   // Arabic
3985fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            strcmp(lang, "fa") == 0 ||   // Persian (Farsi)
3995fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            strcmp(lang, "he") == 0 ||   // Hebrew (new language code)
400b66cb69e3933d5f56f06d88cd31817f49d87df5fDoug Zongker            strcmp(lang, "iw") == 0 ||   // Hebrew (old language code)
401b66cb69e3933d5f56f06d88cd31817f49d87df5fDoug Zongker            strcmp(lang, "ur") == 0) {   // Urdu
4025fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker            rtl_locale = true;
4035fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        }
4045fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker        free(lang);
405a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongker    } else {
406a418aa7dd5e94cbf1ab2a6fa1c63f60e5e087d42Doug Zongker        new_locale = NULL;
4075fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker    }
4085fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker}
4095fa8c23911759a9e81af0e7fb5eb431277b8e9a6Doug Zongker
410211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetBackground(Icon icon)
411c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
412211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
41302ec6b88ed4e6cf40cc257572b07c7277b7b6341Doug Zongker
41452eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    currentIcon = icon;
41552eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker    update_screen_locked();
41652eeea4fa59c15ecb09c32b8e05653f4e55f5188Doug Zongker
417211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
418c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
419c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
420211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetProgressType(ProgressType type)
421c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
422211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
423211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType != type) {
424211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        progressBarType = type;
425c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
42669f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    progressScopeStart = 0;
427239ac6abac4524be93fce710360c0512c6cc2ab3Doug Zongker    progressScopeSize = 0;
42869f4b6732ce13f248b0da0c7eeda56207fdeaba2Doug Zongker    progress = 0;
429239ac6abac4524be93fce710360c0512c6cc2ab3Doug Zongker    update_progress_locked();
430211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
431c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
432c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
433211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::ShowProgress(float portion, float seconds)
434c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
435211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
436211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressBarType = DETERMINATE;
437211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeStart += progressScopeSize;
438211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeSize = portion;
439211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeTime = now();
440211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progressScopeDuration = seconds;
441211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    progress = 0;
442c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    update_progress_locked();
443211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
444c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
445c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
446211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::SetProgress(float fraction)
447c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
448211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
449c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (fraction < 0.0) fraction = 0.0;
450c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (fraction > 1.0) fraction = 1.0;
451211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    if (progressBarType == DETERMINATE && fraction > progress) {
452c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        // Skip updates that aren't visibly different.
453eac881c952fc6be0beeb5f719e3a70e651f3610eDoug Zongker        int width = gr_get_width(progressBarEmpty);
454211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        float scale = width * progressScopeSize;
455211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker        if ((int) (progress * scale) != (int) (fraction * scale)) {
456211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker            progress = fraction;
457c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            update_progress_locked();
458c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
459c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
460211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
461c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
462c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
463c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongkervoid ScreenRecoveryUI::SetStage(int current, int max) {
464c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker    pthread_mutex_lock(&updateMutex);
465c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker    stage = current;
466c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker    max_stage = max;
467c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker    pthread_mutex_unlock(&updateMutex);
468c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker}
469c87bab101893e8322b49d7c8600e3367b20ab50aDoug Zongker
470211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::Print(const char *fmt, ...)
471c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
472c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    char buf[256];
473c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_list ap;
474c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_start(ap, fmt);
475c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    vsnprintf(buf, 256, fmt, ap);
476c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    va_end(ap);
477c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
4783d177d055c9cf3571e4b7c098818b454d1dbf9d7Doug Zongker    fputs(buf, stdout);
479c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
480c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    // This can get called before ui_init(), so be careful.
481211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
482c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (text_rows > 0 && text_cols > 0) {
483c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        char *ptr;
484c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (ptr = buf; *ptr != '\0'; ++ptr) {
485c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (*ptr == '\n' || text_col >= text_cols) {
486c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text[text_row][text_col] = '\0';
487c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text_col = 0;
488c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                text_row = (text_row + 1) % text_rows;
489c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project                if (text_row == text_top) text_top = (text_top + 1) % text_rows;
490c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            }
491c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (*ptr != '\n') text[text_row][text_col++] = *ptr;
492c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
493c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        text[text_row][text_col] = '\0';
494c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
495c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
496211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
497c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
498c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
499211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::StartMenu(const char* const * headers, const char* const * items,
500211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker                                 int initial_selection) {
501c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int i;
502211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
503c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (text_rows > 0 && text_cols > 0) {
504c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (i = 0; i < text_rows; ++i) {
505c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (headers[i] == NULL) break;
506c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            strncpy(menu[i], headers[i], text_cols-1);
507c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            menu[i][text_cols-1] = '\0';
508c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
509c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_top = i;
510c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        for (; i < text_rows; ++i) {
511c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            if (items[i-menu_top] == NULL) break;
512c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            strncpy(menu[i], items[i-menu_top], text_cols-1);
513c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project            menu[i][text_cols-1] = '\0';
514c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        }
515c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_items = i - menu_top;
516c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        show_menu = 1;
517be598881d079511385a88b12b7a14b97e63dc85eDoug Zongker        menu_sel = initial_selection;
518c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
519c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
520211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
521c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
522c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
523211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerint ScreenRecoveryUI::SelectMenu(int sel) {
524c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int old_sel;
525211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
526c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (show_menu > 0) {
527c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        old_sel = menu_sel;
528c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        menu_sel = sel;
529c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel < 0) menu_sel = 0;
530c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel >= menu_items) menu_sel = menu_items-1;
531c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        sel = menu_sel;
532c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        if (menu_sel != old_sel) update_screen_locked();
533c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
534211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
535c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    return sel;
536c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
537c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
538211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::EndMenu() {
539c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int i;
540211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
541c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    if (show_menu > 0 && text_rows > 0 && text_cols > 0) {
542c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        show_menu = 0;
543c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project        update_screen_locked();
544c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    }
545211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
546c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
547c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
548211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerbool ScreenRecoveryUI::IsTextVisible()
549c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project{
550211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
551c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    int visible = show_text;
552211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
553c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project    return visible;
554c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project}
555c24a8e688a6312764254beac2b2520bb0c5e998dThe Android Open Source Project
556211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkerbool ScreenRecoveryUI::WasTextEverVisible()
5575cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker{
558211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
5595cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    int ever_visible = show_text_ever;
560211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
5615cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    return ever_visible;
5625cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker}
5635cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker
564211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongkervoid ScreenRecoveryUI::ShowText(bool visible)
5654bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker{
566211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_lock(&updateMutex);
5674bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker    show_text = visible;
5685cae445e43c5928daba0a76745b0dd2657274edaDoug Zongker    if (show_text) show_text_ever = 1;
5694bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker    update_screen_locked();
570211aebc4e09ce7ca37003be4f01c83111cf0bb49Doug Zongker    pthread_mutex_unlock(&updateMutex);
5714bc980626c1cf6f1ea7d36e4b54e0023c896c9deDoug Zongker}
572c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker
573c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongkervoid ScreenRecoveryUI::Redraw()
574c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker{
575c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker    pthread_mutex_lock(&updateMutex);
576c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker    update_screen_locked();
577c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker    pthread_mutex_unlock(&updateMutex);
578c0441d171914e59941ec4f815ae0aabf56d6504fDoug Zongker}
579