Merge "EmulatedFakeCamera2: Use HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED" into jb-mr1-dev
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkVars.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkVars.java
index ff3a686..9abfe26 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkVars.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceNetworkVars.java
@@ -15,7 +15,7 @@
*/
package com.android.commands.monkey;
-import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
import android.os.SystemClock;
import android.view.Display;
@@ -82,7 +82,7 @@
VAR_MAP.put("build.version.codename", new StaticVarGetter(Build.VERSION.CODENAME));
// Display
- Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
+ Display display = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
VAR_MAP.put("display.width", new StaticVarGetter(Integer.toString(display.getWidth())));
VAR_MAP.put("display.height", new StaticVarGetter(Integer.toString(display.getHeight())));
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
index e0ebd03..a7f538d 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
@@ -18,7 +18,7 @@
import android.content.ComponentName;
import android.graphics.PointF;
-import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerGlobal;
import android.os.SystemClock;
import android.view.Display;
import android.view.KeyCharacterMap;
@@ -259,7 +259,7 @@
*
*/
private void generatePointerEvent(Random random, int gesture) {
- Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
+ Display display = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
PointF p1 = randomPoint(random, display);
PointF v1 = randomVector(random);
diff --git a/host/windows/usb/android_winusb.inf b/host/windows/usb/android_winusb.inf
index b4462cd..f26a75c 100755
--- a/host/windows/usb/android_winusb.inf
+++ b/host/windows/usb/android_winusb.inf
@@ -6,15 +6,10 @@
Class = AndroidUsbDeviceClass
ClassGuid = {3F966BD9-FA04-4ec5-991C-D326973B5128}
Provider = %ProviderName%
-DriverVer = 05/24/2012,6.0.0000.00000
+DriverVer = 08/27/2012,7.0.0000.00001
CatalogFile.NTx86 = androidwinusb86.cat
CatalogFile.NTamd64 = androidwinusba64.cat
-;
-; This section seems to be required for WinUsb driver installation.
-; If this section is removed the installer will report an error
-; "Required section not found in INF file".
-;
[ClassInstall32]
Addreg = AndroidWinUsbClassReg
@@ -22,9 +17,11 @@
HKR,,,0,%ClassName%
HKR,,Icon,,-1
+
[Manufacturer]
%ProviderName% = Google, NTx86, NTamd64
+
[Google.NTx86]
;Google Nexus One
@@ -46,6 +43,21 @@
%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E42&MI_01
%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E44&MI_01
+;Google Nexus Q
+%SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_2C10
+%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_2C11
+
+;Google Nexus (generic)
+%SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4EE0
+%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE1
+%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE2
+%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE2&MI_01
+%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE3
+%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE4&MI_01
+%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE5
+%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE6&MI_01
+
+
[Google.NTamd64]
;Google Nexus One
@@ -67,6 +79,20 @@
%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E42&MI_01
%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E44&MI_01
+;Google Nexus Q
+%SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_2C10
+%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_2C11
+
+;Google Nexus (generic)
+%SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4EE0
+%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE1
+%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE2
+%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE2&MI_01
+%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE3
+%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE4&MI_01
+%SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE5
+%CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE6&MI_01
+
[USB_Install]
Include = winusb.inf
Needs = WINUSB.NT
@@ -127,4 +153,4 @@
SingleBootLoaderInterface = "Android Bootloader Interface"
WinUSB_SvcDesc = "Android USB Driver"
DISK_NAME = "Android WinUsb installation disk"
-ClassName = "Android Phone"
+ClassName = "Android Device"
diff --git a/host/windows/usb/readme.txt b/host/windows/usb/readme.txt
index 961b45a..d01bc98 100755
--- a/host/windows/usb/readme.txt
+++ b/host/windows/usb/readme.txt
@@ -15,7 +15,7 @@
* WdfCoInstaller01007.dll
* WinUSBCoInstaller.dll
* WUDFUpdate_01007.dll
-
+
File contained in i386 and amd64 subfolders are Microsoft distributives needed
to install WinUsb framework. These files can be obtained from WDK 'redist'
folder, respectively to the OS: copy x86 files to i386 subfolder, and amd64
diff --git a/ide/eclipse/.classpath b/ide/eclipse/.classpath
index 0626e5f..bb34b54 100644
--- a/ide/eclipse/.classpath
+++ b/ide/eclipse/.classpath
@@ -11,9 +11,11 @@
<classpathentry kind="src" path="packages/apps/DeskClock/src"/>
<classpathentry kind="src" path="packages/apps/Email/src"/>
<classpathentry kind="src" path="packages/apps/Email/emailcommon/src"/>
+ <classpathentry kind="src" path="packages/apps/Email/emailsync/src"/>
<classpathentry kind="src" path="packages/apps/Gallery2/src"/>
<classpathentry kind="src" path="packages/apps/Gallery2/src_pd"/>
<classpathentry kind="src" path="packages/apps/Gallery2/gallerycommon/src"/>
+ <classpathentry kind="src" path="packages/apps/Gallery2/actionbarsherlock/src"/>
<classpathentry kind="src" path="packages/apps/HTMLViewer/src"/>
<classpathentry kind="src" path="packages/apps/Launcher2/src"/>
<classpathentry kind="src" path="packages/apps/Mms/src"/>
diff --git a/ndk/platforms/android-5/samples/hello-gl2/default.properties b/ndk/platforms/android-5/samples/hello-gl2/default.properties
index dbf05f2..9d135cb 100644
--- a/ndk/platforms/android-5/samples/hello-gl2/default.properties
+++ b/ndk/platforms/android-5/samples/hello-gl2/default.properties
@@ -8,4 +8,4 @@
# project structure.
# Project target.
-target=android-5
+target=android-7
diff --git a/ndk/platforms/android-9/arch-mips/src/crtbegin_so.S b/ndk/platforms/android-9/arch-mips/src/crtbegin_so.S
index f4fc9b8..68dddfe 100644
--- a/ndk/platforms/android-9/arch-mips/src/crtbegin_so.S
+++ b/ndk/platforms/android-9/arch-mips/src/crtbegin_so.S
@@ -38,24 +38,7 @@
.long -1
.long __do_global_dtors_aux
- .section .ctors, "aw"
- .type __CTOR_LIST__, @object
- .globl __CTOR_LIST__
-__CTOR_LIST__:
- .long -1
-
- .section .dtors, "aw"
- .type __DTOR_LIST__, @object
- .globl __DTOR_LIST__
-__DTOR_LIST__:
- .long -1
-
.abicalls
- .section .eh_frame,"a",@progbits
- .align 2
- .type __EH_FRAME_BEGIN__, @object
- .size __EH_FRAME_BEGIN__, 0
-__EH_FRAME_BEGIN__:
.text
.align 2
.set nomips16
@@ -105,8 +88,6 @@
.size __do_global_dtors_aux, .-__do_global_dtors_aux
.local completed.1269
.comm completed.1269,1,1
- .local object.1265
- .comm object.1265,24,4
.weak __cxa_finalize
.include "__dso_handle.S"
diff --git a/ndk/platforms/android-9/arch-mips/src/crtend_so.S b/ndk/platforms/android-9/arch-mips/src/crtend_so.S
index d0bb090..f09c427 100644
--- a/ndk/platforms/android-9/arch-mips/src/crtend_so.S
+++ b/ndk/platforms/android-9/arch-mips/src/crtend_so.S
@@ -3,21 +3,3 @@
.section .fini_array, "aw"
.long 0
-
- .section .ctors, "aw", @progbits
- .type __CTOR_END__, @object
-__CTOR_END__:
- .long 0
-
- .section .dtors, "aw", @progbits
- .type __DTOR_END__, @object
-__DTOR_END__:
- .long 0
-
- .section .eh_frame,"a",@progbits
- .align 4
- .type __FRAME_END__, @object
- .size __FRAME_END__, 4
-__FRAME_END__:
- .zero 4
-
diff --git a/ndk/platforms/android-9/samples/native-activity/default.properties b/ndk/platforms/android-9/samples/native-activity/default.properties
index 9a2c9f6..8010039 100644
--- a/ndk/platforms/android-9/samples/native-activity/default.properties
+++ b/ndk/platforms/android-9/samples/native-activity/default.properties
@@ -8,4 +8,4 @@
# project structure.
# Project target.
-target=android-9
+target=android-10
diff --git a/ndk/platforms/android-9/samples/native-activity/jni/Application.mk b/ndk/platforms/android-9/samples/native-activity/jni/Application.mk
index 22d188e..682f11b 100644
--- a/ndk/platforms/android-9/samples/native-activity/jni/Application.mk
+++ b/ndk/platforms/android-9/samples/native-activity/jni/Application.mk
@@ -1 +1 @@
-APP_PLATFORM := android-9
+APP_PLATFORM := android-10
diff --git a/ndk/platforms/android-9/samples/native-audio/default.properties b/ndk/platforms/android-9/samples/native-audio/default.properties
index eada70a..d63a41e 100644
--- a/ndk/platforms/android-9/samples/native-audio/default.properties
+++ b/ndk/platforms/android-9/samples/native-audio/default.properties
@@ -8,6 +8,6 @@
# project structure.
# Project target.
-target=android-9
+target=android-10
# Indicates whether an apk should be generated for each density.
split.density=false
diff --git a/ndk/platforms/android-9/samples/native-plasma/default.properties b/ndk/platforms/android-9/samples/native-plasma/default.properties
index 9a2c9f6..8010039 100644
--- a/ndk/platforms/android-9/samples/native-plasma/default.properties
+++ b/ndk/platforms/android-9/samples/native-plasma/default.properties
@@ -8,4 +8,4 @@
# project structure.
# Project target.
-target=android-9
+target=android-10
diff --git a/ndk/platforms/android-9/samples/native-plasma/jni/Application.mk b/ndk/platforms/android-9/samples/native-plasma/jni/Application.mk
index 23fa139..70bbb62 100644
--- a/ndk/platforms/android-9/samples/native-plasma/jni/Application.mk
+++ b/ndk/platforms/android-9/samples/native-plasma/jni/Application.mk
@@ -1,3 +1,3 @@
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi armeabi-v7a
-APP_PLATFORM := android-9
+APP_PLATFORM := android-10
diff --git a/sdk/usbdriver_source.properties b/sdk/usbdriver_source.properties
index 73ddf74..bff71f9 100755
--- a/sdk/usbdriver_source.properties
+++ b/sdk/usbdriver_source.properties
@@ -1,4 +1,4 @@
-Pkg.Revision=6
+Pkg.Revision=7
Archive.Os=WINDOWS
Archive.Arch=ANY
Extra.Path=usb_driver
diff --git a/tools/recovery_l10n/Android.mk b/tools/recovery_l10n/Android.mk
new file mode 100644
index 0000000..937abd1
--- /dev/null
+++ b/tools/recovery_l10n/Android.mk
@@ -0,0 +1,12 @@
+# Copyright 2012 Google Inc. All Rights Reserved.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := RecoveryLocalizer
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_PACKAGE)
diff --git a/tools/recovery_l10n/AndroidManifest.xml b/tools/recovery_l10n/AndroidManifest.xml
new file mode 100644
index 0000000..8c51a4e
--- /dev/null
+++ b/tools/recovery_l10n/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.recovery_l10n">
+
+ <application android:label="Recovery Localizer">
+ <activity android:name="Main"
+ android:label="Recovery Localizer">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
+
+
diff --git a/tools/recovery_l10n/res/layout/main.xml b/tools/recovery_l10n/res/layout/main.xml
new file mode 100644
index 0000000..1ac2b24
--- /dev/null
+++ b/tools/recovery_l10n/res/layout/main.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ >
+
+ <Spinner android:id="@+id/which"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
+
+ <Button android:id="@+id/go"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/go"
+ />
+
+ <TextView android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#ffffffff"
+ android:background="#ff000000"
+ android:maxWidth="480px"
+ />
+
+
+</LinearLayout>
+
+
diff --git a/tools/recovery_l10n/res/values-de/strings.xml b/tools/recovery_l10n/res/values-de/strings.xml
new file mode 100644
index 0000000..a03803d
--- /dev/null
+++ b/tools/recovery_l10n/res/values-de/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="recovery_installing">Systemupdate wird installiert\u2026</string>
+ <string name="recovery_erasing">Löschen\u2026</string>
+ <string name="recovery_no_command">Kein Befehl.</string>
+ <string name="recovery_error">Fehler!</string>
+
+</resources>
diff --git a/tools/recovery_l10n/res/values/strings.xml b/tools/recovery_l10n/res/values/strings.xml
new file mode 100644
index 0000000..3a8aeec
--- /dev/null
+++ b/tools/recovery_l10n/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Do not translate. -->
+ <string translatable="false" name="go">Go</string>
+
+ <!-- Do not translate. -->
+ <string-array translatable="false" name="string_options">
+ <item>installing</item>
+ <item>erasing</item>
+ <item>no_command</item>
+ <item>error</item>
+ </string-array>
+
+ <!-- Displayed on the screen beneath the animated android while the
+ system is installing an update. [CHAR LIMIT=60] -->
+ <string name="recovery_installing">Installing system update\u2026</string>
+
+ <!-- Displayed on the screen beneath the animated android while the
+ system is erasing a partition (either a data wipe aka "factory
+ reset", or a cache wipe). [CHAR LIMIT=60] -->
+ <string name="recovery_erasing">Erasing\u2026</string>
+
+ <!-- Displayed on the screen when the user has gotten into recovery
+ mode without a command to run. Will not normally happen, but
+ users (especially developers) may boot into recovery mode
+ manually via special key combinations. [CHAR LIMIT=60] -->
+ <string name="recovery_no_command">No command.</string>
+
+ <!-- Displayed on the triangle-! screen when a system update
+ installation or data wipe procedure encounters an error. [CHAR
+ LIMIT=60] -->
+ <string name="recovery_error">Error!</string>
+
+</resources>
diff --git a/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java b/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
new file mode 100644
index 0000000..63ae3ea
--- /dev/null
+++ b/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.recovery_l10n;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.AssetManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Spinner;
+import android.widget.ArrayAdapter;
+import android.widget.AdapterView;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Locale;
+import java.util.HashMap;
+
+/**
+ * This activity assists in generating the specially-formatted bitmaps
+ * of text needed for recovery's localized text display. Each image
+ * contains all the translations of a single string; above each
+ * translation is a "header row" that encodes that subimage's width,
+ * height, and locale using pixel values.
+ *
+ * To use this app to generate new translations:
+ *
+ * - Update the string resources in res/values-*
+ *
+ * - Update the list of desired locales (mLocales) below. Locales
+ * should be ordered by decreasing popularity (ie, the most
+ * commonly-used one first).
+ *
+ * - Build and run the app. Select the string you want to
+ * translate, and press the "Go" button.
+ *
+ * - Wait for it to finish cycling through all the strings, then
+ * pull /data/data/com.android.recovery_l10n/files/text-out.png
+ * from the device.
+ *
+ * - "pngcrush -c 0 text-out.png output.png"
+ *
+ * - Put output.png in bootable/recovery/res/images/ (renamed
+ * appropriately).
+ *
+ * Recovery expects 8-bit 1-channel images (white text on black
+ * background). pngcrush -c 0 will convert the output of this program
+ * to such an image. If you use any other image handling tools,
+ * remember that they must be lossless to preserve the exact values of
+ * pixels in the header rows; don't convert them to jpeg or anything.
+ */
+
+public class Main extends Activity {
+ private static final String TAG = "RecoveryL10N";
+
+ final Locale[] mLocales = new Locale[] { Locale.US, Locale.GERMANY };
+
+ HashMap<Locale, Bitmap> savedBitmaps;
+ TextView mText;
+ int mStringId = R.string.recovery_installing;
+
+ public class TextCapture implements Runnable {
+ private Locale nextLocale;
+ private Locale thisLocale;
+ private Runnable next;
+
+ TextCapture(Locale thisLocale, Locale nextLocale, Runnable next) {
+ this.nextLocale = nextLocale;
+ this.thisLocale = thisLocale;
+ this.next = next;
+ }
+
+ public void run() {
+ Bitmap b = mText.getDrawingCache();
+ savedBitmaps.put(thisLocale, b.copy(Bitmap.Config.ARGB_8888, false));
+
+ if (nextLocale != null) {
+ switchTo(nextLocale);
+ }
+
+ if (next != null) {
+ mText.postDelayed(next, 200);
+ }
+ }
+ }
+
+ private void switchTo(Locale locale) {
+ Resources standardResources = getResources();
+ AssetManager assets = standardResources.getAssets();
+ DisplayMetrics metrics = standardResources.getDisplayMetrics();
+ Configuration config = new Configuration(standardResources.getConfiguration());
+ config.locale = locale;
+ Resources defaultResources = new Resources(assets, metrics, config);
+
+ mText.setText(mStringId);
+
+ mText.setDrawingCacheEnabled(false);
+ mText.setDrawingCacheEnabled(true);
+ mText.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstance) {
+ super.onCreate(savedInstance);
+ setContentView(R.layout.main);
+
+ savedBitmaps = new HashMap<Locale, Bitmap>();
+
+ Spinner spinner = (Spinner) findViewById(R.id.which);
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
+ this, R.array.string_options, android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView parent, View view,
+ int pos, long id) {
+ switch (pos) {
+ case 0: mStringId = R.string.recovery_installing; break;
+ case 1: mStringId = R.string.recovery_erasing; break;
+ case 2: mStringId = R.string.recovery_no_command; break;
+ case 3: mStringId = R.string.recovery_error; break;
+ }
+ }
+ @Override public void onNothingSelected(AdapterView parent) { }
+ });
+
+ mText = (TextView) findViewById(R.id.text);
+
+ final Runnable seq = buildSequence(mLocales);
+
+ Button b = (Button) findViewById(R.id.go);
+ b.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View ignore) {
+ mText.post(seq);
+ }
+ });
+ }
+
+ private Runnable buildSequence(final Locale[] locales) {
+ Runnable head = new Runnable() { public void run() { mergeBitmaps(locales); } };
+ Locale prev = null;
+ for (Locale loc : locales) {
+ head = new TextCapture(loc, prev, head);
+ prev = loc;
+ }
+ final Runnable fhead = head;
+ final Locale floc = prev;
+ return new Runnable() { public void run() { startSequence(fhead, floc); } };
+ }
+
+ private void startSequence(Runnable firstRun, Locale firstLocale) {
+ savedBitmaps.clear();
+ switchTo(firstLocale);
+ mText.postDelayed(firstRun, 200);
+ }
+
+ private void saveBitmap(Bitmap b, String filename) {
+ try {
+ FileOutputStream fos = openFileOutput(filename, 0);
+ b.compress(Bitmap.CompressFormat.PNG, 100, fos);
+ fos.close();
+ } catch (IOException e) {
+ Log.i(TAG, "failed to write PNG", e);
+ }
+ }
+
+ private int colorFor(byte b) {
+ return 0xff000000 | (b<<16) | (b<<8) | b;
+ }
+
+ private int colorFor(int b) {
+ return 0xff000000 | (b<<16) | (b<<8) | b;
+ }
+
+ private void mergeBitmaps(final Locale[] locales) {
+ HashMap<String, Integer> countByLanguage = new HashMap<String, Integer>();
+
+ int height = 2;
+ int width = 10;
+ int maxHeight = 0;
+ for (Locale loc : locales) {
+ Bitmap b = savedBitmaps.get(loc);
+ int h = b.getHeight();
+ int w = b.getWidth();
+ height += h+1;
+ if (h > maxHeight) maxHeight = h;
+ if (w > width) width = w;
+
+ String lang = loc.getLanguage();
+ if (countByLanguage.containsKey(lang)) {
+ countByLanguage.put(lang, countByLanguage.get(lang)+1);
+ } else {
+ countByLanguage.put(lang, 1);
+ }
+ }
+
+ Log.i(TAG, "output bitmap is " + width + " x " + height);
+ Bitmap out = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ out.eraseColor(0xff000000);
+ int[] pixels = new int[maxHeight * width];
+
+ int p = 0;
+ for (Locale loc : locales) {
+ Bitmap bm = savedBitmaps.get(loc);
+ int h = bm.getHeight();
+ int w = bm.getWidth();
+
+ String lang = loc.getLanguage();
+ if (countByLanguage.get(lang) > 1) {
+ lang = loc.toString();
+ }
+ Log.i(TAG, "encoding \"" + loc + "\" as \"" + lang + "\"");
+ byte[] langBytes = lang.getBytes();
+ out.setPixel(0, p, colorFor(w & 0xff));
+ out.setPixel(1, p, colorFor(w >>> 8));
+ out.setPixel(2, p, colorFor(h & 0xff));
+ out.setPixel(3, p, colorFor(h >>> 8));
+ out.setPixel(4, p, colorFor(langBytes.length));
+ int x = 5;
+ for (byte b : langBytes) {
+ out.setPixel(x, p, colorFor(b));
+ x++;
+ }
+ out.setPixel(x, p, colorFor(0));
+
+ p++;
+
+ bm.getPixels(pixels, 0, w, 0, 0, w, h);
+ out.setPixels(pixels, 0, w, 0, p, w, h);
+ p += h;
+ }
+
+ // if no languages match, suppress text display by using a
+ // single black pixel as the image.
+ out.setPixel(0, p, colorFor(1));
+ out.setPixel(1, p, colorFor(0));
+ out.setPixel(2, p, colorFor(1));
+ out.setPixel(3, p, colorFor(0));
+ out.setPixel(4, p, colorFor(0));
+ p++;
+
+ saveBitmap(out, "text-out.png");
+ }
+}