summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2013-11-22 11:18:57 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2013-11-22 11:18:57 -0800
commitdbccd44a638ae8705a5b14bff8b2dd74abc26045 (patch)
tree14bfabaf3f3c7be86dfc064e919e00433a0cf2bb /tools
parentecfae4f899873f224e1aeed076dc8a41f8884487 (diff)
parentb873a17ce7be0a9771c24999adca6964431728f6 (diff)
downloadframeworks_base-dbccd44a638ae8705a5b14bff8b2dd74abc26045.zip
frameworks_base-dbccd44a638ae8705a5b14bff8b2dd74abc26045.tar.gz
frameworks_base-dbccd44a638ae8705a5b14bff8b2dd74abc26045.tar.bz2
Merge commit 'b873a17ce7be0a9771c24999adca6964431728f6' into HEAD
Change-Id: I938755073e70602cc8f51ce9bd420fdcf870cecd
Diffstat (limited to 'tools')
-rw-r--r--tools/aapt/Android.mk48
-rw-r--r--tools/aapt/Command.cpp337
-rw-r--r--tools/aapt/Package.cpp3
-rw-r--r--tools/aapt/Resource.cpp28
-rw-r--r--tools/aapt/ResourceTable.cpp69
-rw-r--r--tools/aapt/StringPool.cpp2
-rw-r--r--tools/aapt/StringPool.h1
-rw-r--r--tools/aapt/WorkQueue.cpp171
-rw-r--r--tools/aapt/WorkQueue.h119
-rw-r--r--tools/aapt/XMLNode.cpp2
-rw-r--r--tools/aapt/ZipFile.cpp2
-rw-r--r--tools/aapt/pseudolocalize.cpp119
-rw-r--r--tools/aapt/pseudolocalize.h9
-rw-r--r--tools/aapt/qsort_r_compat.c90
-rw-r--r--tools/aapt/qsort_r_compat.h39
-rw-r--r--tools/aidl/aidl.cpp10
-rw-r--r--tools/layoutlib/Android.mk4
-rw-r--r--tools/layoutlib/bridge/.classpath1
-rw-r--r--tools/layoutlib/bridge/Android.mk1
-rw-r--r--tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.pngbin0 -> 904 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.pngbin0 -> 533 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.pngbin0 -> 617 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.pngbin0 -> 423 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.pngbin0 -> 1250 bytes
-rw-r--r--tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.pngbin0 -> 552 bytes
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java215
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java11
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java89
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java97
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java136
-rw-r--r--tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java31
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java46
-rw-r--r--tools/layoutlib/bridge/src/android/webkit/WebView.java16
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java20
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java18
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java34
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java8
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java8
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java26
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java13
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java5
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java22
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java3
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java28
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java (renamed from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java)137
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java74
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java24
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java50
-rw-r--r--tools/obbtool/Android.mk2
-rw-r--r--tools/preload/Policy.java5
-rw-r--r--tools/validatekeymaps/Android.mk4
-rw-r--r--tools/validatekeymaps/Main.cpp6
52 files changed, 1683 insertions, 500 deletions
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 9b1658a..452c60a 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -7,10 +7,8 @@
# This tool is prebuilt if we're doing an app-only build.
ifeq ($(TARGET_BUILD_APPS),)
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
+aapt_src_files := \
AaptAssets.cpp \
Command.cpp \
CrunchCache.cpp \
@@ -24,23 +22,29 @@ LOCAL_SRC_FILES := \
ResourceTable.cpp \
Images.cpp \
Resource.cpp \
+ pseudolocalize.cpp \
SourcePos.cpp \
+ WorkQueue.cpp \
ZipEntry.cpp \
- ZipFile.cpp
+ ZipFile.cpp \
+ qsort_r_compat.c
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(aapt_src_files)
LOCAL_CFLAGS += -Wno-format-y2k
ifeq (darwin,$(HOST_OS))
LOCAL_CFLAGS += -D_DARWIN_UNLIMITED_STREAMS
endif
+LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
LOCAL_C_INCLUDES += external/libpng
LOCAL_C_INCLUDES += external/zlib
-LOCAL_C_INCLUDES += build/libs/host/include
LOCAL_STATIC_LIBRARIES := \
- libhost \
libandroidfw \
libutils \
libcutils \
@@ -64,4 +68,36 @@ LOCAL_MODULE := aapt
include $(BUILD_HOST_EXECUTABLE)
+# aapt for running on the device
+# =========================================================
+ifneq ($(SDK_ONLY),true)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(aapt_src_files)
+
+LOCAL_MODULE := aapt
+
+LOCAL_C_INCLUDES += bionic
+LOCAL_C_INCLUDES += bionic/libstdc++/include
+LOCAL_C_INCLUDES += external/stlport/stlport
+LOCAL_C_INCLUDES += external/libpng
+LOCAL_C_INCLUDES += external/zlib
+
+LOCAL_CFLAGS += -Wno-non-virtual-dtor
+
+LOCAL_SHARED_LIBRARIES := \
+ libandroidfw \
+ libutils \
+ libcutils \
+ libpng \
+ liblog \
+ libz
+
+LOCAL_STATIC_LIBRARIES := \
+ libstlport_static \
+ libexpat_static
+
+include $(BUILD_EXECUTABLE)
+endif
+
endif # TARGET_BUILD_APPS
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index cadac02..632efe0 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -346,6 +346,8 @@ enum {
LABEL_ATTR = 0x01010001,
ICON_ATTR = 0x01010002,
NAME_ATTR = 0x01010003,
+ PERMISSION_ATTR = 0x01010006,
+ RESOURCE_ATTR = 0x01010025,
DEBUGGABLE_ATTR = 0x0101000f,
VERSION_CODE_ATTR = 0x0101021b,
VERSION_NAME_ATTR = 0x0101021c,
@@ -372,6 +374,7 @@ enum {
COMPATIBLE_WIDTH_LIMIT_DP_ATTR = 0x01010365,
LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
PUBLIC_KEY_ATTR = 0x010103a6,
+ CATEGORY_ATTR = 0x010103e8,
};
const char *getComponentName(String8 &pkgName, String8 &componentName) {
@@ -424,6 +427,61 @@ static void printCompatibleScreens(ResXMLTree& tree) {
printf("\n");
}
+Vector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost,
+ String8 *outError = NULL)
+{
+ Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER);
+ if (aidAsset == NULL) {
+ if (outError != NULL) *outError = "xml resource does not exist";
+ return Vector<String8>();
+ }
+
+ const String8 serviceTagName(offHost ? "offhost-apdu-service" : "host-apdu-service");
+
+ bool withinApduService = false;
+ Vector<String8> categories;
+
+ String8 error;
+ ResXMLTree tree;
+ tree.setTo(aidAsset->getBuffer(true), aidAsset->getLength());
+
+ size_t len;
+ int depth = 0;
+ ResXMLTree::event_code_t code;
+ while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+ if (code == ResXMLTree::END_TAG) {
+ depth--;
+ String8 tag(tree.getElementName(&len));
+
+ if (depth == 0 && tag == serviceTagName) {
+ withinApduService = false;
+ }
+
+ } else if (code == ResXMLTree::START_TAG) {
+ depth++;
+ String8 tag(tree.getElementName(&len));
+
+ if (depth == 1) {
+ if (tag == serviceTagName) {
+ withinApduService = true;
+ }
+ } else if (depth == 2 && withinApduService) {
+ if (tag == "aid-group") {
+ String8 category = getAttribute(tree, CATEGORY_ATTR, &error);
+ if (error != "") {
+ if (outError != NULL) *outError = error;
+ return Vector<String8>();
+ }
+
+ categories.add(category);
+ }
+ }
+ }
+ }
+ aidAsset->close();
+ return categories;
+}
+
/*
* Handle the "dump" command, to extract select data from an archive.
*/
@@ -621,6 +679,7 @@ int doDump(Bundle* bundle)
bool isLauncherActivity = false;
bool isSearchable = false;
bool withinApplication = false;
+ bool withinSupportsInput = false;
bool withinReceiver = false;
bool withinService = false;
bool withinIntentFilter = false;
@@ -630,12 +689,31 @@ int doDump(Bundle* bundle)
bool hasOtherServices = false;
bool hasWallpaperService = false;
bool hasImeService = false;
+ bool hasAccessibilityService = false;
+ bool hasPrintService = false;
bool hasWidgetReceivers = false;
+ bool hasDeviceAdminReceiver = false;
bool hasIntentFilter = false;
+ bool hasPaymentService = false;
bool actMainActivity = false;
bool actWidgetReceivers = false;
+ bool actDeviceAdminEnabled = false;
bool actImeService = false;
bool actWallpaperService = false;
+ bool actAccessibilityService = false;
+ bool actPrintService = false;
+ bool actHostApduService = false;
+ bool actOffHostApduService = false;
+ bool hasMetaHostPaymentCategory = false;
+ bool hasMetaOffHostPaymentCategory = false;
+
+ // These permissions are required by services implementing services
+ // the system binds to (IME, Accessibility, PrintServices, etc.)
+ bool hasBindDeviceAdminPermission = false;
+ bool hasBindInputMethodPermission = false;
+ bool hasBindAccessibilityServicePermission = false;
+ bool hasBindPrintServicePermission = false;
+ bool hasBindNfcServicePermission = false;
// These two implement the implicit permissions that are granted
// to pre-1.6 applications.
@@ -711,11 +789,26 @@ int doDump(Bundle* bundle)
String8 activityIcon;
String8 receiverName;
String8 serviceName;
+ Vector<String8> supportedInput;
while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
if (code == ResXMLTree::END_TAG) {
depth--;
if (depth < 2) {
+ if (withinSupportsInput && !supportedInput.isEmpty()) {
+ printf("supports-input: '");
+ const size_t N = supportedInput.size();
+ for (size_t i=0; i<N; i++) {
+ printf("%s", supportedInput[i].string());
+ if (i != N - 1) {
+ printf("' '");
+ } else {
+ printf("'\n");
+ }
+ }
+ supportedInput.clear();
+ }
withinApplication = false;
+ withinSupportsInput = false;
} else if (depth < 3) {
if (withinActivity && isMainActivity && isLauncherActivity) {
const char *aName = getComponentName(pkg, activityName);
@@ -731,6 +824,13 @@ int doDump(Bundle* bundle)
hasOtherActivities |= withinActivity;
hasOtherReceivers |= withinReceiver;
hasOtherServices |= withinService;
+ } else {
+ if (withinService) {
+ hasPaymentService |= (actHostApduService && hasMetaHostPaymentCategory &&
+ hasBindNfcServicePermission);
+ hasPaymentService |= (actOffHostApduService && hasMetaOffHostPaymentCategory &&
+ hasBindNfcServicePermission);
+ }
}
withinActivity = false;
withinService = false;
@@ -744,11 +844,18 @@ int doDump(Bundle* bundle)
hasOtherActivities |= !actMainActivity;
} else if (withinReceiver) {
hasWidgetReceivers |= actWidgetReceivers;
- hasOtherReceivers |= !actWidgetReceivers;
+ hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
+ hasBindDeviceAdminPermission);
+ hasOtherReceivers |= (!actWidgetReceivers && !actDeviceAdminEnabled);
} else if (withinService) {
hasImeService |= actImeService;
hasWallpaperService |= actWallpaperService;
- hasOtherServices |= (!actImeService && !actWallpaperService);
+ hasAccessibilityService |= (actAccessibilityService &&
+ hasBindAccessibilityServicePermission);
+ hasPrintService |= (actPrintService && hasBindPrintServicePermission);
+ hasOtherServices |= (!actImeService && !actWallpaperService &&
+ !actAccessibilityService && !actPrintService &&
+ !actHostApduService && !actOffHostApduService);
}
}
withinIntentFilter = false;
@@ -910,6 +1017,8 @@ int doDump(Bundle* bundle)
printf(" reqFiveWayNav='%d'", reqFiveWayNav);
}
printf("\n");
+ } else if (tag == "supports-input") {
+ withinSupportsInput = true;
} else if (tag == "supports-screens") {
smallScreen = getIntegerAttribute(tree,
SMALL_SCREEN_ATTR, NULL, 1);
@@ -1086,73 +1195,175 @@ int doDump(Bundle* bundle)
}
}
}
- } else if (depth == 3 && withinApplication) {
+ } else if (depth == 3) {
withinActivity = false;
withinReceiver = false;
withinService = false;
hasIntentFilter = false;
- if(tag == "activity") {
- withinActivity = true;
- activityName = getAttribute(tree, NAME_ATTR, &error);
- if (error != "") {
- fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string());
- goto bail;
- }
+ hasMetaHostPaymentCategory = false;
+ hasMetaOffHostPaymentCategory = false;
+ hasBindDeviceAdminPermission = false;
+ hasBindInputMethodPermission = false;
+ hasBindAccessibilityServicePermission = false;
+ hasBindPrintServicePermission = false;
+ hasBindNfcServicePermission = false;
+ if (withinApplication) {
+ if(tag == "activity") {
+ withinActivity = true;
+ activityName = getAttribute(tree, NAME_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
+ error.string());
+ goto bail;
+ }
- activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
- if (error != "") {
- fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n", error.string());
- goto bail;
- }
+ activityLabel = getResolvedAttribute(&res, tree, LABEL_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:label' attribute: %s\n",
+ error.string());
+ goto bail;
+ }
- activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
- if (error != "") {
- fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n", error.string());
- goto bail;
- }
+ activityIcon = getResolvedAttribute(&res, tree, ICON_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:icon' attribute: %s\n",
+ error.string());
+ goto bail;
+ }
+
+ int32_t orien = getResolvedIntegerAttribute(&res, tree,
+ SCREEN_ORIENTATION_ATTR, &error);
+ if (error == "") {
+ if (orien == 0 || orien == 6 || orien == 8) {
+ // Requests landscape, sensorLandscape, or reverseLandscape.
+ reqScreenLandscapeFeature = true;
+ } else if (orien == 1 || orien == 7 || orien == 9) {
+ // Requests portrait, sensorPortrait, or reversePortrait.
+ reqScreenPortraitFeature = true;
+ }
+ }
+ } else if (tag == "uses-library") {
+ String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr,
+ "ERROR getting 'android:name' attribute for uses-library"
+ " %s\n", error.string());
+ goto bail;
+ }
+ int req = getIntegerAttribute(tree,
+ REQUIRED_ATTR, NULL, 1);
+ printf("uses-library%s:'%s'\n",
+ req ? "" : "-not-required", libraryName.string());
+ } else if (tag == "receiver") {
+ withinReceiver = true;
+ receiverName = getAttribute(tree, NAME_ATTR, &error);
- int32_t orien = getResolvedIntegerAttribute(&res, tree,
- SCREEN_ORIENTATION_ATTR, &error);
- if (error == "") {
- if (orien == 0 || orien == 6 || orien == 8) {
- // Requests landscape, sensorLandscape, or reverseLandscape.
- reqScreenLandscapeFeature = true;
- } else if (orien == 1 || orien == 7 || orien == 9) {
- // Requests portrait, sensorPortrait, or reversePortrait.
- reqScreenPortraitFeature = true;
+ if (error != "") {
+ fprintf(stderr,
+ "ERROR getting 'android:name' attribute for receiver:"
+ " %s\n", error.string());
+ goto bail;
+ }
+
+ String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
+ if (error == "") {
+ if (permission == "android.permission.BIND_DEVICE_ADMIN") {
+ hasBindDeviceAdminPermission = true;
+ }
+ } else {
+ fprintf(stderr, "ERROR getting 'android:permission' attribute for"
+ " receiver '%s': %s\n", receiverName.string(), error.string());
+ }
+ } else if (tag == "service") {
+ withinService = true;
+ serviceName = getAttribute(tree, NAME_ATTR, &error);
+
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:name' attribute for"
+ " service: %s\n", error.string());
+ goto bail;
+ }
+
+ String8 permission = getAttribute(tree, PERMISSION_ATTR, &error);
+ if (error == "") {
+ if (permission == "android.permission.BIND_INPUT_METHOD") {
+ hasBindInputMethodPermission = true;
+ } else if (permission == "android.permission.BIND_ACCESSIBILITY_SERVICE") {
+ hasBindAccessibilityServicePermission = true;
+ } else if (permission == "android.permission.BIND_PRINT_SERVICE") {
+ hasBindPrintServicePermission = true;
+ } else if (permission == "android.permission.BIND_NFC_SERVICE") {
+ hasBindNfcServicePermission = true;
+ }
+ } else {
+ fprintf(stderr, "ERROR getting 'android:permission' attribute for"
+ " service '%s': %s\n", serviceName.string(), error.string());
}
}
- } else if (tag == "uses-library") {
- String8 libraryName = getAttribute(tree, NAME_ATTR, &error);
- if (error != "") {
- fprintf(stderr, "ERROR getting 'android:name' attribute for uses-library: %s\n", error.string());
+ } else if (withinSupportsInput && tag == "input-type") {
+ String8 name = getAttribute(tree, NAME_ATTR, &error);
+ if (name != "" && error == "") {
+ supportedInput.add(name);
+ } else {
+ fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
+ error.string());
goto bail;
}
- int req = getIntegerAttribute(tree,
- REQUIRED_ATTR, NULL, 1);
- printf("uses-library%s:'%s'\n",
- req ? "" : "-not-required", libraryName.string());
- } else if (tag == "receiver") {
- withinReceiver = true;
- receiverName = getAttribute(tree, NAME_ATTR, &error);
-
+ }
+ } else if (depth == 4) {
+ if (tag == "intent-filter") {
+ hasIntentFilter = true;
+ withinIntentFilter = true;
+ actMainActivity = false;
+ actWidgetReceivers = false;
+ actImeService = false;
+ actWallpaperService = false;
+ actAccessibilityService = false;
+ actPrintService = false;
+ actDeviceAdminEnabled = false;
+ actHostApduService = false;
+ actOffHostApduService = false;
+ } else if (withinService && tag == "meta-data") {
+ String8 name = getAttribute(tree, NAME_ATTR, &error);
if (error != "") {
- fprintf(stderr, "ERROR getting 'android:name' attribute for receiver: %s\n", error.string());
+ fprintf(stderr, "ERROR getting 'android:name' attribute for"
+ " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
goto bail;
}
- } else if (tag == "service") {
- withinService = true;
- serviceName = getAttribute(tree, NAME_ATTR, &error);
- if (error != "") {
- fprintf(stderr, "ERROR getting 'android:name' attribute for service: %s\n", error.string());
- goto bail;
+ if (name == "android.nfc.cardemulation.host_apdu_service" ||
+ name == "android.nfc.cardemulation.off_host_apdu_service") {
+ bool offHost = true;
+ if (name == "android.nfc.cardemulation.host_apdu_service") {
+ offHost = false;
+ }
+
+ String8 xmlPath = getResolvedAttribute(&res, tree, RESOURCE_ATTR, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting 'android:resource' attribute for"
+ " meta-data tag in service '%s': %s\n", serviceName.string(), error.string());
+ goto bail;
+ }
+
+ Vector<String8> categories = getNfcAidCategories(assets, xmlPath,
+ offHost, &error);
+ if (error != "") {
+ fprintf(stderr, "ERROR getting AID category for service '%s'\n",
+ serviceName.string());
+ goto bail;
+ }
+
+ const size_t catLen = categories.size();
+ for (size_t i = 0; i < catLen; i++) {
+ bool paymentCategory = (categories[i] == "payment");
+ if (offHost) {
+ hasMetaOffHostPaymentCategory |= paymentCategory;
+ } else {
+ hasMetaHostPaymentCategory |= paymentCategory;
+ }
+ }
}
}
- } else if ((depth == 4) && (tag == "intent-filter")) {
- hasIntentFilter = true;
- withinIntentFilter = true;
- actMainActivity = actWidgetReceivers = actImeService = actWallpaperService = false;
} else if ((depth == 5) && withinIntentFilter){
String8 action;
if (tag == "action") {
@@ -1169,12 +1380,22 @@ int doDump(Bundle* bundle)
} else if (withinReceiver) {
if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
actWidgetReceivers = true;
+ } else if (action == "android.app.action.DEVICE_ADMIN_ENABLED") {
+ actDeviceAdminEnabled = true;
}
} else if (withinService) {
if (action == "android.view.InputMethod") {
actImeService = true;
} else if (action == "android.service.wallpaper.WallpaperService") {
actWallpaperService = true;
+ } else if (action == "android.accessibilityservice.AccessibilityService") {
+ actAccessibilityService = true;
+ } else if (action == "android.printservice.PrintService") {
+ actPrintService = true;
+ } else if (action == "android.nfc.cardemulation.action.HOST_APDU_SERVICE") {
+ actHostApduService = true;
+ } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
+ actOffHostApduService = true;
}
}
if (action == "android.intent.action.SEARCH") {
@@ -1374,12 +1595,24 @@ int doDump(Bundle* bundle)
if (hasWidgetReceivers) {
printf("app-widget\n");
}
+ if (hasDeviceAdminReceiver) {
+ printf("device-admin\n");
+ }
if (hasImeService) {
printf("ime\n");
}
if (hasWallpaperService) {
printf("wallpaper\n");
}
+ if (hasAccessibilityService) {
+ printf("accessibility\n");
+ }
+ if (hasPrintService) {
+ printf("print\n");
+ }
+ if (hasPaymentService) {
+ printf("payment\n");
+ }
if (hasOtherActivities) {
printf("other-activities\n");
}
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index 3930117..872d95c 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -8,10 +8,13 @@
#include "ResourceTable.h"
#include "ResourceFilter.h"
+#include <androidfw/misc.h>
+
#include <utils/Log.h>
#include <utils/threads.h>
#include <utils/List.h>
#include <utils/Errors.h>
+#include <utils/misc.h>
#include <sys/types.h>
#include <dirent.h>
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 490d8e6..386888b 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -14,7 +14,7 @@
#include "FileFinder.h"
#include "CacheUpdater.h"
-#include <utils/WorkQueue.h>
+#include "WorkQueue.h"
#if HAVE_PRINTF_ZD
# define ZD "%zd"
@@ -172,6 +172,7 @@ private:
bool isValidResourceType(const String8& type)
{
return type == "anim" || type == "animator" || type == "interpolator"
+ || type == "transition"
|| type == "drawable" || type == "layout"
|| type == "values" || type == "xml" || type == "raw"
|| type == "color" || type == "menu" || type == "mipmap";
@@ -932,6 +933,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
sp<ResourceTypeSet> anims;
sp<ResourceTypeSet> animators;
sp<ResourceTypeSet> interpolators;
+ sp<ResourceTypeSet> transitions;
sp<ResourceTypeSet> xmls;
sp<ResourceTypeSet> raws;
sp<ResourceTypeSet> colors;
@@ -943,6 +945,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
ASSIGN_IT(anim);
ASSIGN_IT(animator);
ASSIGN_IT(interpolator);
+ ASSIGN_IT(transition);
ASSIGN_IT(xml);
ASSIGN_IT(raw);
ASSIGN_IT(color);
@@ -965,6 +968,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
!applyFileOverlay(bundle, assets, &anims, "anim") ||
!applyFileOverlay(bundle, assets, &animators, "animator") ||
!applyFileOverlay(bundle, assets, &interpolators, "interpolator") ||
+ !applyFileOverlay(bundle, assets, &transitions, "transition") ||
!applyFileOverlay(bundle, assets, &xmls, "xml") ||
!applyFileOverlay(bundle, assets, &raws, "raw") ||
!applyFileOverlay(bundle, assets, &colors, "color") ||
@@ -1024,6 +1028,13 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
}
}
+ if (transitions != NULL) {
+ err = makeFileResources(bundle, assets, &table, transitions, "transition");
+ if (err != NO_ERROR) {
+ hasErrors = true;
+ }
+ }
+
if (interpolators != NULL) {
err = makeFileResources(bundle, assets, &table, interpolators, "interpolator");
if (err != NO_ERROR) {
@@ -1168,6 +1179,21 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets)
err = NO_ERROR;
}
+ if (transitions != NULL) {
+ ResourceDirIterator it(transitions, String8("transition"));
+ while ((err=it.next()) == NO_ERROR) {
+ err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+ if (err != NO_ERROR) {
+ hasErrors = true;
+ }
+ }
+
+ if (err < NO_ERROR) {
+ hasErrors = true;
+ }
+ err = NO_ERROR;
+ }
+
if (xmls != NULL) {
ResourceDirIterator it(xmls, String8("xml"));
while ((err=it.next()) == NO_ERROR) {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 52ebaf0..f2e5254 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -636,6 +636,30 @@ bool isInProductList(const String16& needle, const String16& haystack) {
return false;
}
+/*
+ * A simple container that holds a resource type and name. It is ordered first by type then
+ * by name.
+ */
+struct type_ident_pair_t {
+ String16 type;
+ String16 ident;
+
+ type_ident_pair_t() { };
+ type_ident_pair_t(const String16& t, const String16& i) : type(t), ident(i) { }
+ type_ident_pair_t(const type_ident_pair_t& o) : type(o.type), ident(o.ident) { }
+ inline bool operator < (const type_ident_pair_t& o) const {
+ int cmp = compare_type(type, o.type);
+ if (cmp < 0) {
+ return true;
+ } else if (cmp > 0) {
+ return false;
+ } else {
+ return strictly_order_type(ident, o.ident);
+ }
+ }
+};
+
+
status_t parseAndAddEntry(Bundle* bundle,
const sp<AaptFile>& in,
ResXMLTree* block,
@@ -650,6 +674,7 @@ status_t parseAndAddEntry(Bundle* bundle,
const String16& product,
bool pseudolocalize,
const bool overwrite,
+ KeyedVector<type_ident_pair_t, bool>* skippedResourceNames,
ResourceTable* outTable)
{
status_t err;
@@ -684,6 +709,13 @@ status_t parseAndAddEntry(Bundle* bundle,
if (bundleProduct[0] == '\0') {
if (strcmp16(String16("default").string(), product.string()) != 0) {
+ /*
+ * This string has a product other than 'default'. Do not add it,
+ * but record it so that if we do not see the same string with
+ * product 'default' or no product, then report an error.
+ */
+ skippedResourceNames->replaceValueFor(
+ type_ident_pair_t(curType, ident), true);
return NO_ERROR;
}
} else {
@@ -797,6 +829,11 @@ status_t compileResourceFile(Bundle* bundle,
DefaultKeyedVector<String16, uint32_t> nextPublicId(0);
+ // Stores the resource names that were skipped. Typically this happens when
+ // AAPT is invoked without a product specified and a resource has no
+ // 'default' product attribute.
+ KeyedVector<type_ident_pair_t, bool> skippedResourceNames;
+
ResXMLTree::event_code_t code;
do {
code = block.next();
@@ -1544,7 +1581,7 @@ status_t compileResourceFile(Bundle* bundle,
err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
*curTag, curIsStyled, curFormat, curIsFormatted,
- product, false, overwrite, outTable);
+ product, false, overwrite, &skippedResourceNames, outTable);
if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
hasErrors = localHasErrors = true;
@@ -1557,7 +1594,7 @@ status_t compileResourceFile(Bundle* bundle,
err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
ident, *curTag, curIsStyled, curFormat,
curIsFormatted, product,
- true, overwrite, outTable);
+ true, overwrite, &skippedResourceNames, outTable);
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;
}
@@ -1596,6 +1633,30 @@ status_t compileResourceFile(Bundle* bundle,
}
}
+ // For every resource defined, there must be exist one variant with a product attribute
+ // set to 'default' (or no product attribute at all).
+ // We check to see that for every resource that was ignored because of a mismatched
+ // product attribute, some product variant of that resource was processed.
+ for (size_t i = 0; i < skippedResourceNames.size(); i++) {
+ if (skippedResourceNames[i]) {
+ const type_ident_pair_t& p = skippedResourceNames.keyAt(i);
+ if (!outTable->hasBagOrEntry(myPackage, p.type, p.ident)) {
+ const char* bundleProduct =
+ (bundle->getProduct() == NULL) ? "" : bundle->getProduct();
+ fprintf(stderr, "In resource file %s: %s\n",
+ in->getPrintableSource().string(),
+ curParams.toString().string());
+
+ fprintf(stderr, "\t%s '%s' does not match product %s.\n"
+ "\tYou may have forgotten to include a 'default' product variant"
+ " of the resource.\n",
+ String8(p.type).string(), String8(p.ident).string(),
+ bundleProduct[0] == 0 ? "default" : bundleProduct);
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+
return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
}
@@ -2483,8 +2544,8 @@ status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
String16 comment(c->getComment());
typeSymbols->appendComment(String8(c->getName()), comment, c->getPos());
- //printf("Type symbol %s comment: %s\n", String8(e->getName()).string(),
- // String8(comment).string());
+ //printf("Type symbol [%08x] %s comment: %s\n", rid,
+ // String8(c->getName()).string(), String8(comment).string());
comment = c->getTypeComment();
typeSymbols->appendTypeComment(String8(c->getName()), comment);
} else {
diff --git a/tools/aapt/StringPool.cpp b/tools/aapt/StringPool.cpp
index 839eda5..158b391 100644
--- a/tools/aapt/StringPool.cpp
+++ b/tools/aapt/StringPool.cpp
@@ -9,7 +9,7 @@
#include <utils/ByteOrder.h>
#include <utils/SortedVector.h>
-#include <cutils/qsort_r_compat.h>
+#include "qsort_r_compat.h"
#if HAVE_PRINTF_ZD
# define ZD "%zd"
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index 16050b2..1b3abfd 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -12,7 +12,6 @@
#include <androidfw/ResourceTypes.h>
#include <utils/String16.h>
-#include <utils/TextOutput.h>
#include <utils/TypeHelpers.h>
#include <sys/types.h>
diff --git a/tools/aapt/WorkQueue.cpp b/tools/aapt/WorkQueue.cpp
new file mode 100644
index 0000000..24a962f
--- /dev/null
+++ b/tools/aapt/WorkQueue.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "WorkQueue"
+
+#include <utils/Log.h>
+#include "WorkQueue.h"
+
+namespace android {
+
+// --- WorkQueue ---
+
+WorkQueue::WorkQueue(size_t maxThreads, bool canCallJava) :
+ mMaxThreads(maxThreads), mCanCallJava(canCallJava),
+ mCanceled(false), mFinished(false), mIdleThreads(0) {
+}
+
+WorkQueue::~WorkQueue() {
+ if (!cancel()) {
+ finish();
+ }
+}
+
+status_t WorkQueue::schedule(WorkUnit* workUnit, size_t backlog) {
+ AutoMutex _l(mLock);
+
+ if (mFinished || mCanceled) {
+ return INVALID_OPERATION;
+ }
+
+ if (mWorkThreads.size() < mMaxThreads
+ && mIdleThreads < mWorkUnits.size() + 1) {
+ sp<WorkThread> workThread = new WorkThread(this, mCanCallJava);
+ status_t status = workThread->run("WorkQueue::WorkThread");
+ if (status) {
+ return status;
+ }
+ mWorkThreads.add(workThread);
+ mIdleThreads += 1;
+ } else if (backlog) {
+ while (mWorkUnits.size() >= mMaxThreads * backlog) {
+ mWorkDequeuedCondition.wait(mLock);
+ if (mFinished || mCanceled) {
+ return INVALID_OPERATION;
+ }
+ }
+ }
+
+ mWorkUnits.add(workUnit);
+ mWorkChangedCondition.broadcast();
+ return OK;
+}
+
+status_t WorkQueue::cancel() {
+ AutoMutex _l(mLock);
+
+ return cancelLocked();
+}
+
+status_t WorkQueue::cancelLocked() {
+ if (mFinished) {
+ return INVALID_OPERATION;
+ }
+
+ if (!mCanceled) {
+ mCanceled = true;
+
+ size_t count = mWorkUnits.size();
+ for (size_t i = 0; i < count; i++) {
+ delete mWorkUnits.itemAt(i);
+ }
+ mWorkUnits.clear();
+ mWorkChangedCondition.broadcast();
+ mWorkDequeuedCondition.broadcast();
+ }
+ return OK;
+}
+
+status_t WorkQueue::finish() {
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (mFinished) {
+ return INVALID_OPERATION;
+ }
+
+ mFinished = true;
+ mWorkChangedCondition.broadcast();
+ } // release lock
+
+ // It is not possible for the list of work threads to change once the mFinished
+ // flag has been set, so we can access mWorkThreads outside of the lock here.
+ size_t count = mWorkThreads.size();
+ for (size_t i = 0; i < count; i++) {
+ mWorkThreads.itemAt(i)->join();
+ }
+ mWorkThreads.clear();
+ return OK;
+}
+
+bool WorkQueue::threadLoop() {
+ WorkUnit* workUnit;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ for (;;) {
+ if (mCanceled) {
+ return false;
+ }
+
+ if (!mWorkUnits.isEmpty()) {
+ workUnit = mWorkUnits.itemAt(0);
+ mWorkUnits.removeAt(0);
+ mIdleThreads -= 1;
+ mWorkDequeuedCondition.broadcast();
+ break;
+ }
+
+ if (mFinished) {
+ return false;
+ }
+
+ mWorkChangedCondition.wait(mLock);
+ }
+ } // release lock
+
+ bool shouldContinue = workUnit->run();
+ delete workUnit;
+
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ mIdleThreads += 1;
+
+ if (!shouldContinue) {
+ cancelLocked();
+ return false;
+ }
+ } // release lock
+
+ return true;
+}
+
+// --- WorkQueue::WorkThread ---
+
+WorkQueue::WorkThread::WorkThread(WorkQueue* workQueue, bool canCallJava) :
+ Thread(canCallJava), mWorkQueue(workQueue) {
+}
+
+WorkQueue::WorkThread::~WorkThread() {
+}
+
+bool WorkQueue::WorkThread::threadLoop() {
+ return mWorkQueue->threadLoop();
+}
+
+}; // namespace android
diff --git a/tools/aapt/WorkQueue.h b/tools/aapt/WorkQueue.h
new file mode 100644
index 0000000..d38f05d
--- /dev/null
+++ b/tools/aapt/WorkQueue.h
@@ -0,0 +1,119 @@
+/*]
+ * 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.
+ */
+
+#ifndef AAPT_WORK_QUEUE_H
+#define AAPT_WORK_QUEUE_H
+
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+/*
+ * A threaded work queue.
+ *
+ * This class is designed to make it easy to run a bunch of isolated work
+ * units in parallel, using up to the specified number of threads.
+ * To use it, write a loop to post work units to the work queue, then synchronize
+ * on the queue at the end.
+ */
+class WorkQueue {
+public:
+ class WorkUnit {
+ public:
+ WorkUnit() { }
+ virtual ~WorkUnit() { }
+
+ /*
+ * Runs the work unit.
+ * If the result is 'true' then the work queue continues scheduling work as usual.
+ * If the result is 'false' then the work queue is canceled.
+ */
+ virtual bool run() = 0;
+ };
+
+ /* Creates a work queue with the specified maximum number of work threads. */
+ WorkQueue(size_t maxThreads, bool canCallJava = true);
+
+ /* Destroys the work queue.
+ * Cancels pending work and waits for all remaining threads to complete.
+ */
+ ~WorkQueue();
+
+ /* Posts a work unit to run later.
+ * If the work queue has been canceled or is already finished, returns INVALID_OPERATION
+ * and does not take ownership of the work unit (caller must destroy it itself).
+ * Otherwise, returns OK and takes ownership of the work unit (the work queue will
+ * destroy it automatically).
+ *
+ * For flow control, this method blocks when the size of the pending work queue is more
+ * 'backlog' times the number of threads. This condition reduces the rate of entry into
+ * the pending work queue and prevents it from growing much more rapidly than the
+ * work threads can actually handle.
+ *
+ * If 'backlog' is 0, then no throttle is applied.
+ */
+ status_t schedule(WorkUnit* workUnit, size_t backlog = 2);
+
+ /* Cancels all pending work.
+ * If the work queue is already finished, returns INVALID_OPERATION.
+ * If the work queue is already canceled, returns OK and does nothing else.
+ * Otherwise, returns OK, discards all pending work units and prevents additional
+ * work units from being scheduled.
+ *
+ * Call finish() after cancel() to wait for all remaining work to complete.
+ */
+ status_t cancel();
+
+ /* Waits for all work to complete.
+ * If the work queue is already finished, returns INVALID_OPERATION.
+ * Otherwise, waits for all work to complete and returns OK.
+ */
+ status_t finish();
+
+private:
+ class WorkThread : public Thread {
+ public:
+ WorkThread(WorkQueue* workQueue, bool canCallJava);
+ virtual ~WorkThread();
+
+ private:
+ virtual bool threadLoop();
+
+ WorkQueue* const mWorkQueue;
+ };
+
+ status_t cancelLocked();
+ bool threadLoop(); // called from each work thread
+
+ const size_t mMaxThreads;
+ const bool mCanCallJava;
+
+ Mutex mLock;
+ Condition mWorkChangedCondition;
+ Condition mWorkDequeuedCondition;
+
+ bool mCanceled;
+ bool mFinished;
+ size_t mIdleThreads;
+ Vector<sp<WorkThread> > mWorkThreads;
+ Vector<WorkUnit*> mWorkUnits;
+};
+
+}; // namespace android
+
+#endif // AAPT_WORK_QUEUE_H
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index dcbe7db..a663ad5 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -6,8 +6,8 @@
#include "XMLNode.h"
#include "ResourceTable.h"
+#include "pseudolocalize.h"
-#include <host/pseudolocalize.h>
#include <utils/ByteOrder.h>
#include <errno.h>
#include <string.h>
diff --git a/tools/aapt/ZipFile.cpp b/tools/aapt/ZipFile.cpp
index 3994c31..8057068 100644
--- a/tools/aapt/ZipFile.cpp
+++ b/tools/aapt/ZipFile.cpp
@@ -20,8 +20,8 @@
#define LOG_TAG "zip"
+#include <androidfw/ZipUtils.h>
#include <utils/Log.h>
-#include <utils/ZipUtils.h>
#include "ZipFile.h"
diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp
new file mode 100644
index 0000000..9e50c5a
--- /dev/null
+++ b/tools/aapt/pseudolocalize.cpp
@@ -0,0 +1,119 @@
+#include "pseudolocalize.h"
+
+using namespace std;
+
+static const char*
+pseudolocalize_char(char c)
+{
+ switch (c) {
+ case 'a': return "\xc4\x83";
+ case 'b': return "\xcf\x84";
+ case 'c': return "\xc4\x8b";
+ case 'd': return "\xc4\x8f";
+ case 'e': return "\xc4\x99";
+ case 'f': return "\xc6\x92";
+ case 'g': return "\xc4\x9d";
+ case 'h': return "\xd1\x9b";
+ case 'i': return "\xcf\x8a";
+ case 'j': return "\xc4\xb5";
+ case 'k': return "\xc4\xb8";
+ case 'l': return "\xc4\xba";
+ case 'm': return "\xe1\xb8\xbf";
+ case 'n': return "\xd0\xb8";
+ case 'o': return "\xcf\x8c";
+ case 'p': return "\xcf\x81";
+ case 'q': return "\x51";
+ case 'r': return "\xd2\x91";
+ case 's': return "\xc5\xa1";
+ case 't': return "\xd1\x82";
+ case 'u': return "\xce\xb0";
+ case 'v': return "\x56";
+ case 'w': return "\xe1\xba\x85";
+ case 'x': return "\xd1\x85";
+ case 'y': return "\xe1\xbb\xb3";
+ case 'z': return "\xc5\xba";
+ case 'A': return "\xc3\x85";
+ case 'B': return "\xce\xb2";
+ case 'C': return "\xc4\x88";
+ case 'D': return "\xc4\x90";
+ case 'E': return "\xd0\x84";
+ case 'F': return "\xce\x93";
+ case 'G': return "\xc4\x9e";
+ case 'H': return "\xc4\xa6";
+ case 'I': return "\xd0\x87";
+ case 'J': return "\xc4\xb5";
+ case 'K': return "\xc4\xb6";
+ case 'L': return "\xc5\x81";
+ case 'M': return "\xe1\xb8\xbe";
+ case 'N': return "\xc5\x83";
+ case 'O': return "\xce\x98";
+ case 'P': return "\xcf\x81";
+ case 'Q': return "\x71";
+ case 'R': return "\xd0\xaf";
+ case 'S': return "\xc8\x98";
+ case 'T': return "\xc5\xa6";
+ case 'U': return "\xc5\xa8";
+ case 'V': return "\xce\xbd";
+ case 'W': return "\xe1\xba\x84";
+ case 'X': return "\xc3\x97";
+ case 'Y': return "\xc2\xa5";
+ case 'Z': return "\xc5\xbd";
+ default: return NULL;
+ }
+}
+
+/**
+ * Converts characters so they look like they've been localized.
+ *
+ * Note: This leaves escape sequences untouched so they can later be
+ * processed by ResTable::collectString in the normal way.
+ */
+string
+pseudolocalize_string(const string& source)
+{
+ const char* s = source.c_str();
+ string result;
+ const size_t I = source.length();
+ for (size_t i=0; i<I; i++) {
+ char c = s[i];
+ if (c == '\\') {
+ if (i<I-1) {
+ result += '\\';
+ i++;
+ c = s[i];
+ switch (c) {
+ case 'u':
+ // this one takes up 5 chars
+ result += string(s+i, 5);
+ i += 4;
+ break;
+ case 't':
+ case 'n':
+ case '#':
+ case '@':
+ case '?':
+ case '"':
+ case '\'':
+ case '\\':
+ default:
+ result += c;
+ break;
+ }
+ } else {
+ result += c;
+ }
+ } else {
+ const char* p = pseudolocalize_char(c);
+ if (p != NULL) {
+ result += p;
+ } else {
+ result += c;
+ }
+ }
+ }
+
+ //printf("result=\'%s\'\n", result.c_str());
+ return result;
+}
+
+
diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h
new file mode 100644
index 0000000..94cb034
--- /dev/null
+++ b/tools/aapt/pseudolocalize.h
@@ -0,0 +1,9 @@
+#ifndef HOST_PSEUDOLOCALIZE_H
+#define HOST_PSEUDOLOCALIZE_H
+
+#include <string>
+
+std::string pseudolocalize_string(const std::string& source);
+
+#endif // HOST_PSEUDOLOCALIZE_H
+
diff --git a/tools/aapt/qsort_r_compat.c b/tools/aapt/qsort_r_compat.c
new file mode 100644
index 0000000..2a8dbe8
--- /dev/null
+++ b/tools/aapt/qsort_r_compat.c
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include "qsort_r_compat.h"
+
+/*
+ * Note: This code is only used on the host, and is primarily here for
+ * Mac OS compatibility. Apparently, glibc and Apple's libc disagree on
+ * the parameter order for qsort_r.
+ */
+
+#if HAVE_BSD_QSORT_R
+
+/*
+ * BSD qsort_r parameter order is as we have defined here.
+ */
+
+void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
+ int (*compar)(void*, const void* , const void*)) {
+ qsort_r(base, nel, width, thunk, compar);
+}
+
+#elif HAVE_GNU_QSORT_R
+
+/*
+ * GNU qsort_r parameter order places the thunk parameter last.
+ */
+
+struct compar_data {
+ void* thunk;
+ int (*compar)(void*, const void* , const void*);
+};
+
+static int compar_wrapper(const void* a, const void* b, void* data) {
+ struct compar_data* compar_data = (struct compar_data*)data;
+ return compar_data->compar(compar_data->thunk, a, b);
+}
+
+void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
+ int (*compar)(void*, const void* , const void*)) {
+ struct compar_data compar_data;
+ compar_data.thunk = thunk;
+ compar_data.compar = compar;
+ qsort_r(base, nel, width, compar_wrapper, &compar_data);
+}
+
+#else
+
+/*
+ * Emulate qsort_r using thread local storage to access the thunk data.
+ */
+
+#include <cutils/threads.h>
+
+static thread_store_t compar_data_key = THREAD_STORE_INITIALIZER;
+
+struct compar_data {
+ void* thunk;
+ int (*compar)(void*, const void* , const void*);
+};
+
+static int compar_wrapper(const void* a, const void* b) {
+ struct compar_data* compar_data = (struct compar_data*)thread_store_get(&compar_data_key);
+ return compar_data->compar(compar_data->thunk, a, b);
+}
+
+void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
+ int (*compar)(void*, const void* , const void*)) {
+ struct compar_data compar_data;
+ compar_data.thunk = thunk;
+ compar_data.compar = compar;
+ thread_store_set(&compar_data_key, &compar_data, NULL);
+ qsort(base, nel, width, compar_wrapper);
+}
+
+#endif
diff --git a/tools/aapt/qsort_r_compat.h b/tools/aapt/qsort_r_compat.h
new file mode 100644
index 0000000..e14f999
--- /dev/null
+++ b/tools/aapt/qsort_r_compat.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+/*
+ * Provides a portable version of qsort_r, called qsort_r_compat, which is a
+ * reentrant variant of qsort that passes a user data pointer to its comparator.
+ * This implementation follows the BSD parameter convention.
+ */
+
+#ifndef ___QSORT_R_COMPAT_H
+#define ___QSORT_R_COMPAT_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk,
+ int (*compar)(void*, const void* , const void* ));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ___QSORT_R_COMPAT_H
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index b5c3da9..a84d743 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -673,6 +673,16 @@ generate_dep_file(const Options& options, const document_item_type* items)
fprintf(to, "\n");
+ // Output "<imported_file>: " so make won't fail if the imported file has
+ // been deleted, moved or renamed in incremental build.
+ import = g_imports;
+ while (import) {
+ if (import->filename) {
+ fprintf(to, "%s :\n", import->filename);
+ }
+ import = import->next;
+ }
+
fclose(to);
}
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index b27ce0e..4e73568 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -25,8 +25,8 @@ include $(CLEAR_VARS)
# We need to process the framework classes.jar file, but we can't
# depend directly on it (private vars won't be inherited correctly).
# So, we depend on framework's BUILT file.
-built_framework_dep := $(call java-lib-deps,framework)
-built_framework_classes := $(call java-lib-files,framework)
+built_framework_dep := $(call java-lib-deps,framework-base)
+built_framework_classes := $(call java-lib-files,framework-base)
built_core_dep := $(call java-lib-deps,core)
built_core_classes := $(call java-lib-files,core)
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index 3c124d9..2e4274d 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -7,5 +7,6 @@
<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/>
<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/>
+ <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/icu4j/icu4j.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 687a91f..e3d48fc 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -22,6 +22,7 @@ LOCAL_JAVA_RESOURCE_DIRS := resources
LOCAL_JAVA_LIBRARIES := \
kxml2-2.3.0 \
+ icu4j \
layoutlib_api-prebuilt \
tools-common-prebuilt
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..782ebfe
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..677b471
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..a1b8062
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..fcdbefe
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..633d864
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..4665e2a
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
new file mode 100644
index 0000000..62d0a0d
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2013 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 android.graphics;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.ibm.icu.lang.UScript;
+import com.ibm.icu.lang.UScriptRun;
+
+import android.graphics.Paint_Delegate.FontInfo;
+
+/**
+ * Render the text by breaking it into various scripts and using the right font for each script.
+ * Can be used to measure the text without actually drawing it.
+ */
+@SuppressWarnings("deprecation")
+public class BidiRenderer {
+
+ /* package */ static class ScriptRun {
+ int start;
+ int limit;
+ boolean isRtl;
+ int scriptCode;
+ FontInfo font;
+
+ public ScriptRun(int start, int limit, boolean isRtl) {
+ this.start = start;
+ this.limit = limit;
+ this.isRtl = isRtl;
+ this.scriptCode = UScript.INVALID_CODE;
+ }
+ }
+
+ /* package */ Graphics2D graphics;
+ /* package */ Paint_Delegate paint;
+ /* package */ char[] text;
+
+ /**
+ * @param graphics May be null.
+ * @param paint The Paint to use to get the fonts. Should not be null.
+ * @param text Unidirectional text. Should not be null.
+ */
+ /* package */ BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) {
+ assert (paint != null);
+ this.graphics = graphics;
+ this.paint = paint;
+ this.text = text;
+ }
+
+ /**
+ * Render unidirectional text.
+ *
+ * This method can also be used to measure the width of the text without actually drawing it.
+ *
+ * @param start index of the first character
+ * @param limit index of the first character that should not be rendered.
+ * @param isRtl is the text right-to-left
+ * @param advances If not null, then advances for each character to be rendered are returned
+ * here.
+ * @param advancesIndex index into advances from where the advances need to be filled.
+ * @param draw If true and {@link graphics} is not null, draw the rendered text on the graphics
+ * at the given co-ordinates
+ * @param x The x-coordinate of the left edge of where the text should be drawn on the given
+ * graphics.
+ * @param y The y-coordinate at which to draw the text on the given graphics.
+ * @return The x-coordinate of the right edge of the drawn text. In other words,
+ * x + the width of the text.
+ */
+ /* package */ float renderText(int start, int limit, boolean isRtl, float advances[],
+ int advancesIndex, boolean draw, float x, float y) {
+ // We break the text into scripts and then select font based on it and then render each of
+ // the script runs.
+ for (ScriptRun run : getScriptRuns(text, start, limit, isRtl, paint.getFonts())) {
+ int flag = Font.LAYOUT_NO_LIMIT_CONTEXT | Font.LAYOUT_NO_START_CONTEXT;
+ flag |= isRtl ? Font.LAYOUT_RIGHT_TO_LEFT : Font.LAYOUT_LEFT_TO_RIGHT;
+ x = renderScript(run.start, run.limit, run.font, flag, advances, advancesIndex, draw,
+ x, y);
+ advancesIndex += run.limit - run.start;
+ }
+ return x;
+ }
+
+ /**
+ * Render a script run. Use the preferred font to render as much as possible. This also
+ * implements a fallback mechanism to render characters that cannot be drawn using the
+ * preferred font.
+ *
+ * @return x + width of the text drawn.
+ */
+ private float renderScript(int start, int limit, FontInfo preferredFont, int flag,
+ float advances[], int advancesIndex, boolean draw, float x, float y) {
+ List<FontInfo> fonts = paint.getFonts();
+ if (fonts == null || preferredFont == null) {
+ return x;
+ }
+
+ while (start < limit) {
+ boolean foundFont = false;
+ int canDisplayUpTo = preferredFont.mFont.canDisplayUpTo(text, start, limit);
+ if (canDisplayUpTo == -1) {
+ return render(start, limit, preferredFont, flag, advances, advancesIndex, draw,
+ x, y);
+ } else if (canDisplayUpTo > start) { // can draw something
+ x = render(start, canDisplayUpTo, preferredFont, flag, advances, advancesIndex,
+ draw, x, y);
+ advancesIndex += canDisplayUpTo - start;
+ start = canDisplayUpTo;
+ }
+
+ int charCount = Character.isHighSurrogate(text[start]) ? 2 : 1;
+ for (FontInfo font : fonts) {
+ canDisplayUpTo = font.mFont.canDisplayUpTo(text, start, start + charCount);
+ if (canDisplayUpTo == -1) {
+ x = render(start, start+charCount, font, flag, advances, advancesIndex, draw,
+ x, y);
+ start += charCount;
+ advancesIndex += charCount;
+ foundFont = true;
+ break;
+ }
+ }
+ if (!foundFont) {
+ // No font can display this char. Use the preferred font. The char will most
+ // probably appear as a box or a blank space. We could, probably, use some
+ // heuristics and break the character into the base character and diacritics and
+ // then draw it, but it's probably not worth the effort.
+ x = render(start, start + charCount, preferredFont, flag, advances, advancesIndex,
+ draw, x, y);
+ start += charCount;
+ advancesIndex += charCount;
+ }
+ }
+ return x;
+ }
+
+ /**
+ * Render the text with the given font.
+ */
+ private float render(int start, int limit, FontInfo font, int flag, float advances[],
+ int advancesIndex, boolean draw, float x, float y) {
+
+ float totalAdvance = 0;
+ // Since the metrics don't have anti-aliasing set, we create a new FontRenderContext with
+ // the anti-aliasing set.
+ FontRenderContext f = font.mMetrics.getFontRenderContext();
+ FontRenderContext frc = new FontRenderContext(f.getTransform(), paint.isAntiAliased(),
+ f.usesFractionalMetrics());
+ GlyphVector gv = font.mFont.layoutGlyphVector(frc, text, start, limit, flag);
+ int ng = gv.getNumGlyphs();
+ int[] ci = gv.getGlyphCharIndices(0, ng, null);
+ for (int i = 0; i < ng; i++) {
+ float adv = gv.getGlyphMetrics(i).getAdvanceX();
+ if (advances != null) {
+ int adv_idx = advancesIndex + ci[i];
+ advances[adv_idx] += adv;
+ }
+ totalAdvance += adv;
+ }
+ if (draw && graphics != null) {
+ graphics.drawGlyphVector(gv, x, y);
+ }
+ return x + totalAdvance;
+ }
+
+ // --- Static helper methods ---
+
+ /* package */ static List<ScriptRun> getScriptRuns(char[] text, int start, int limit,
+ boolean isRtl, List<FontInfo> fonts) {
+ LinkedList<ScriptRun> scriptRuns = new LinkedList<ScriptRun>();
+
+ int count = limit - start;
+ UScriptRun uScriptRun = new UScriptRun(text, start, count);
+ while (uScriptRun.next()) {
+ int scriptStart = uScriptRun.getScriptStart();
+ int scriptLimit = uScriptRun.getScriptLimit();
+ ScriptRun run = new ScriptRun(scriptStart, scriptLimit, isRtl);
+ run.scriptCode = uScriptRun.getScriptCode();
+ setScriptFont(text, run, fonts);
+ scriptRuns.add(run);
+ }
+
+ return scriptRuns;
+ }
+
+ // TODO: Replace this method with one which returns the font based on the scriptCode.
+ private static void setScriptFont(char[] text, ScriptRun run,
+ List<FontInfo> fonts) {
+ for (FontInfo fontInfo : fonts) {
+ if (fontInfo.mFont.canDisplayUpTo(text, run.start, run.limit) == -1) {
+ run.font = fontInfo;
+ return;
+ }
+ }
+ run.font = fonts.get(0);
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index 5256b58..04ce9d0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -24,10 +24,13 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.content.res.BridgeResources.NinePatchInputStream;
import android.graphics.BitmapFactory.Options;
+import android.graphics.Bitmap_Delegate.BitmapCreateFlags;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
+import java.util.EnumSet;
+import java.util.Set;
/**
* Delegate implementing the native methods of android.graphics.BitmapFactory
@@ -98,8 +101,12 @@ import java.io.InputStream;
//TODO support rescaling
Density density = Density.MEDIUM;
+ Set<BitmapCreateFlags> bitmapCreateFlags = EnumSet.of(BitmapCreateFlags.MUTABLE);
if (opts != null) {
density = Density.getEnum(opts.inDensity);
+ if (opts.inPremultiplied) {
+ bitmapCreateFlags.add(BitmapCreateFlags.PREMULTIPLIED);
+ }
}
try {
@@ -112,7 +119,7 @@ import java.io.InputStream;
npis, true /*is9Patch*/, false /*convert*/);
// get the bitmap and chunk objects.
- bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
+ bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), bitmapCreateFlags,
density);
NinePatchChunk chunk = ninePatch.getChunk();
@@ -127,7 +134,7 @@ import java.io.InputStream;
padding.bottom = paddingarray[3];
} else {
// load the bitmap directly.
- bm = Bitmap_Delegate.createBitmap(is, true, density);
+ bm = Bitmap_Delegate.createBitmap(is, bitmapCreateFlags, density);
}
} catch (IOException e) {
Bridge.getLog().error(null,"Failed to load image" , e, null);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 96616aa..ec284ac 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -33,6 +33,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.Buffer;
import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Set;
import javax.imageio.ImageIO;
@@ -51,6 +53,10 @@ import javax.imageio.ImageIO;
*/
public final class Bitmap_Delegate {
+ public enum BitmapCreateFlags {
+ PREMULTIPLIED, MUTABLE
+ }
+
// ---- delegate manager ----
private static final DelegateManager<Bitmap_Delegate> sManager =
new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class);
@@ -93,10 +99,25 @@ public final class Bitmap_Delegate {
*/
public static Bitmap createBitmap(File input, boolean isMutable, Density density)
throws IOException {
+ return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
+ }
+
+ /**
+ * Creates and returns a {@link Bitmap} initialized with the given file content.
+ *
+ * @param input the file from which to read the bitmap content
+ * @param density the density associated with the bitmap
+ *
+ * @see Bitmap#isPremultiplied()
+ * @see Bitmap#isMutable()
+ * @see Bitmap#getDensity()
+ */
+ public static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
+ Density density) throws IOException {
// create a delegate with the content of the file.
Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
- return createBitmap(delegate, isMutable, density.getDpiValue());
+ return createBitmap(delegate, createFlags, density.getDpiValue());
}
/**
@@ -111,10 +132,26 @@ public final class Bitmap_Delegate {
*/
public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density)
throws IOException {
+ return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
+ }
+
+ /**
+ * Creates and returns a {@link Bitmap} initialized with the given stream content.
+ *
+ * @param input the stream from which to read the bitmap content
+ * @param createFlags
+ * @param density the density associated with the bitmap
+ *
+ * @see Bitmap#isPremultiplied()
+ * @see Bitmap#isMutable()
+ * @see Bitmap#getDensity()
+ */
+ public static Bitmap createBitmap(InputStream input, Set<BitmapCreateFlags> createFlags,
+ Density density) throws IOException {
// create a delegate with the content of the stream.
Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
- return createBitmap(delegate, isMutable, density.getDpiValue());
+ return createBitmap(delegate, createFlags, density.getDpiValue());
}
/**
@@ -129,10 +166,26 @@ public final class Bitmap_Delegate {
*/
public static Bitmap createBitmap(BufferedImage image, boolean isMutable,
Density density) throws IOException {
+ return createBitmap(image, getPremultipliedBitmapCreateFlags(isMutable), density);
+ }
+
+ /**
+ * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
+ *
+ * @param image the bitmap content
+ * @param createFlags
+ * @param density the density associated with the bitmap
+ *
+ * @see Bitmap#isPremultiplied()
+ * @see Bitmap#isMutable()
+ * @see Bitmap#getDensity()
+ */
+ public static Bitmap createBitmap(BufferedImage image, Set<BitmapCreateFlags> createFlags,
+ Density density) throws IOException {
// create a delegate with the given image.
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
- return createBitmap(delegate, isMutable, density.getDpiValue());
+ return createBitmap(delegate, createFlags, density.getDpiValue());
}
/**
@@ -203,7 +256,7 @@ public final class Bitmap_Delegate {
@LayoutlibDelegate
/*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
- int height, int nativeConfig, boolean mutable) {
+ int height, int nativeConfig, boolean isMutable) {
int imageType = getBufferedImageType(nativeConfig);
// create the image
@@ -216,7 +269,8 @@ public final class Bitmap_Delegate {
// create a delegate with the content of the stream.
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
- return createBitmap(delegate, mutable, Bitmap.getDefaultDensity());
+ return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
+ Bitmap.getDefaultDensity());
}
@LayoutlibDelegate
@@ -244,7 +298,8 @@ public final class Bitmap_Delegate {
// create a delegate with the content of the stream.
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
- return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity());
+ return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
+ Bitmap.getDefaultDensity());
}
@LayoutlibDelegate
@@ -464,7 +519,7 @@ public final class Bitmap_Delegate {
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8);
// the density doesn't matter, it's set by the Java method.
- return createBitmap(delegate, false /*isMutable*/,
+ return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.MUTABLE),
Density.DEFAULT_DENSITY /*density*/);
}
@@ -546,13 +601,27 @@ public final class Bitmap_Delegate {
mConfig = config;
}
- private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
+ private static Bitmap createBitmap(Bitmap_Delegate delegate,
+ Set<BitmapCreateFlags> createFlags, int density) {
// get its native_int
int nativeInt = sManager.addNewDelegate(delegate);
+ int width = delegate.mImage.getWidth();
+ int height = delegate.mImage.getHeight();
+ boolean isMutable = createFlags.contains(BitmapCreateFlags.MUTABLE);
+ boolean isPremultiplied = createFlags.contains(BitmapCreateFlags.PREMULTIPLIED);
+
// and create/return a new Bitmap with it
- return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/,
- density);
+ return new Bitmap(nativeInt, null /* buffer */, width, height, density, isMutable,
+ isPremultiplied, null /*ninePatchChunk*/, null /* layoutBounds */);
+ }
+
+ private static Set<BitmapCreateFlags> getPremultipliedBitmapCreateFlags(boolean isMutable) {
+ Set<BitmapCreateFlags> createFlags = EnumSet.of(BitmapCreateFlags.PREMULTIPLIED);
+ if (isMutable) {
+ createFlags.add(BitmapCreateFlags.MUTABLE);
+ }
+ return createFlags;
}
/**
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 4171bb5..62b47bd 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -23,7 +23,6 @@ import com.android.layoutlib.bridge.impl.GcSnapshot;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.Bitmap.Config;
-import android.graphics.Paint_Delegate.FontInfo;
import android.text.TextUtils;
import java.awt.Color;
@@ -35,7 +34,6 @@ import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.image.BufferedImage;
-import java.util.List;
/**
@@ -978,7 +976,8 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void native_drawText(int nativeCanvas,
final char[] text, final int index, final int count,
- final float startX, final float startY, int flags, int paint) {
+ final float startX, final float startY, final int flags, int paint) {
+
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
@@ -988,10 +987,10 @@ public final class Canvas_Delegate {
// Paint.TextAlign indicates how the text is positioned relative to X.
// LEFT is the default and there's nothing to do.
float x = startX;
- float y = startY;
+ int limit = index + count;
+ boolean isRtl = flags == Canvas.DIRECTION_RTL;
if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
- // TODO: check the value of bidiFlags.
- float m = paintDelegate.measureText(text, index, count, 0);
+ float m = paintDelegate.measureText(text, index, count, isRtl);
if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
x -= m / 2;
} else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
@@ -999,87 +998,15 @@ public final class Canvas_Delegate {
}
}
- List<FontInfo> fonts = paintDelegate.getFonts();
-
- if (fonts.size() > 0) {
- FontInfo mainFont = fonts.get(0);
- int i = index;
- int lastIndex = index + count;
- while (i < lastIndex) {
- // always start with the main font.
- int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
- if (upTo == -1) {
- // draw all the rest and exit.
- graphics.setFont(mainFont.mFont);
- graphics.drawChars(text, i, lastIndex - i, (int)x, (int)y);
- return;
- } else if (upTo > 0) {
- // draw what's possible
- graphics.setFont(mainFont.mFont);
- graphics.drawChars(text, i, upTo - i, (int)x, (int)y);
-
- // compute the width that was drawn to increase x
- x += mainFont.mMetrics.charsWidth(text, i, upTo - i);
-
- // move index to the first non displayed char.
- i = upTo;
-
- // don't call continue at this point. Since it is certain the main font
- // cannot display the font a index upTo (now ==i), we move on to the
- // fallback fonts directly.
- }
-
- // no char supported, attempt to read the next char(s) with the
- // fallback font. In this case we only test the first character
- // and then go back to test with the main font.
- // Special test for 2-char characters.
- boolean foundFont = false;
- for (int f = 1 ; f < fonts.size() ; f++) {
- FontInfo fontInfo = fonts.get(f);
-
- // need to check that the font can display the character. We test
- // differently if the char is a high surrogate.
- int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
- upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
- if (upTo == -1) {
- // draw that char
- graphics.setFont(fontInfo.mFont);
- graphics.drawChars(text, i, charCount, (int)x, (int)y);
-
- // update x
- x += fontInfo.mMetrics.charsWidth(text, i, charCount);
-
- // update the index in the text, and move on
- i += charCount;
- foundFont = true;
- break;
-
- }
- }
-
- // in case no font can display the char, display it with the main font.
- // (it'll put a square probably)
- if (foundFont == false) {
- int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
-
- graphics.setFont(mainFont.mFont);
- graphics.drawChars(text, i, charCount, (int)x, (int)y);
-
- // measure it to advance x
- x += mainFont.mMetrics.charsWidth(text, i, charCount);
-
- // and move to the next chars.
- i += charCount;
- }
- }
- }
+ new BidiRenderer(graphics, paintDelegate, text).renderText(
+ index, limit, isRtl, null, 0, true, x, startY);
}
});
}
@LayoutlibDelegate
/*package*/ static void native_drawText(int nativeCanvas, String text,
- int start, int end, float x, float y, int flags, int paint) {
+ int start, int end, float x, float y, final int flags, int paint) {
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
@@ -1148,14 +1075,6 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_drawPicture(int nativeCanvas,
- int nativePicture) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawPicture is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
/*package*/ static void finalizer(int nativeCanvas) {
// get the delegate from the native int so that it can be disposed.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index c9c9800..41953ed 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -32,7 +32,6 @@ import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -576,7 +575,7 @@ public class Paint_Delegate {
return 0;
}
- return delegate.measureText(text, index, count, bidiFlags);
+ return delegate.measureText(text, index, count, isRtl(bidiFlags));
}
@LayoutlibDelegate
@@ -615,7 +614,7 @@ public class Paint_Delegate {
}
// measure from start to end
- float res = delegate.measureText(text, start, end - start + 1, bidiFlags);
+ float res = delegate.measureText(text, start, end - start + 1, isRtl(bidiFlags));
if (measuredWidth != null) {
measuredWidth[measureIndex] = res;
@@ -980,51 +979,27 @@ public class Paint_Delegate {
/*package*/ static float native_getTextRunAdvances(int native_object,
char[] text, int index, int count, int contextIndex, int contextCount,
int flags, float[] advances, int advancesIndex) {
+
+ if (advances != null)
+ for (int i = advancesIndex; i< advancesIndex+count; i++)
+ advances[i]=0;
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
+ if (delegate == null || delegate.mFonts == null || delegate.mFonts.size() == 0) {
return 0.f;
}
+ boolean isRtl = isRtl(flags);
- if (delegate.mFonts.size() > 0) {
- // FIXME: handle multi-char characters (see measureText)
- float totalAdvance = 0;
- for (int i = 0; i < count; i++) {
- char c = text[i + index];
- boolean found = false;
- for (FontInfo info : delegate.mFonts) {
- if (info.mFont.canDisplay(c)) {
- float adv = info.mMetrics.charWidth(c);
- totalAdvance += adv;
- if (advances != null) {
- advances[i] = adv;
- }
-
- found = true;
- break;
- }
- }
-
- if (found == false) {
- // no advance for this char.
- if (advances != null) {
- advances[i] = 0.f;
- }
- }
- }
-
- return totalAdvance;
- }
-
- return 0;
-
+ int limit = index + count;
+ return new BidiRenderer(null, delegate, text).renderText(
+ index, limit, isRtl, advances, advancesIndex, false, 0, 0);
}
@LayoutlibDelegate
/*package*/ static float native_getTextRunAdvances(int native_object,
String text, int start, int end, int contextStart, int contextEnd,
int flags, float[] advances, int advancesIndex) {
- // FIXME: support contextStart, contextEnd and direction flag
+ // FIXME: support contextStart and contextEnd
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
@@ -1080,19 +1055,12 @@ public class Paint_Delegate {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
+ if (delegate == null || delegate.mFonts == null || delegate.mFonts.size() == 0) {
return;
}
-
- // FIXME should test if the main font can display all those characters.
- // See MeasureText
- if (delegate.mFonts.size() > 0) {
- FontInfo mainInfo = delegate.mFonts.get(0);
-
- Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count,
- delegate.mFontContext);
- bounds.set(0, 0, (int) rect.getWidth(), (int) rect.getHeight());
- }
+ int w = (int) delegate.measureText(text, index, count, isRtl(bidiFlags));
+ int h= delegate.getFonts().get(0).mMetrics.getHeight();
+ bounds.set(0, 0, w, h);
}
@LayoutlibDelegate
@@ -1176,6 +1144,7 @@ public class Paint_Delegate {
info.mFont = info.mFont.deriveFont(new AffineTransform(
mTextScaleX, mTextSkewX, 0, 1, 0, 0));
}
+ // The metrics here don't have anti-aliasing set.
info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont);
infoList.add(info);
@@ -1185,64 +1154,9 @@ public class Paint_Delegate {
}
}
- /*package*/ float measureText(char[] text, int index, int count, int bidiFlags) {
- // TODO: find out what bidiFlags actually does.
-
- // WARNING: the logic in this method is similar to Canvas_Delegate.native_drawText
- // Any change to this method should be reflected there as well
-
- if (mFonts.size() > 0) {
- FontInfo mainFont = mFonts.get(0);
- int i = index;
- int lastIndex = index + count;
- float total = 0f;
- while (i < lastIndex) {
- // always start with the main font.
- int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
- if (upTo == -1) {
- // shortcut to exit
- return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i);
- } else if (upTo > 0) {
- total += mainFont.mMetrics.charsWidth(text, i, upTo - i);
- i = upTo;
- // don't call continue at this point. Since it is certain the main font
- // cannot display the font a index upTo (now ==i), we move on to the
- // fallback fonts directly.
- }
-
- // no char supported, attempt to read the next char(s) with the
- // fallback font. In this case we only test the first character
- // and then go back to test with the main font.
- // Special test for 2-char characters.
- boolean foundFont = false;
- for (int f = 1 ; f < mFonts.size() ; f++) {
- FontInfo fontInfo = mFonts.get(f);
-
- // need to check that the font can display the character. We test
- // differently if the char is a high surrogate.
- int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
- upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
- if (upTo == -1) {
- total += fontInfo.mMetrics.charsWidth(text, i, charCount);
- i += charCount;
- foundFont = true;
- break;
-
- }
- }
-
- // in case no font can display the char, measure it with the main font.
- if (foundFont == false) {
- int size = Character.isHighSurrogate(text[i]) ? 2 : 1;
- total += mainFont.mMetrics.charsWidth(text, i, size);
- i += size;
- }
- }
-
- return total;
- }
-
- return 0;
+ /*package*/ float measureText(char[] text, int index, int count, boolean isRtl) {
+ return new BidiRenderer(null, this, text).renderText(
+ index, index + count, isRtl, null, 0, false, 0, 0);
}
private float getFontMetrics(FontMetrics metrics) {
@@ -1281,4 +1195,14 @@ public class Paint_Delegate {
}
}
+ private static boolean isRtl(int flag) {
+ switch(flag) {
+ case Paint.BIDI_RTL:
+ case Paint.BIDI_FORCE_RTL:
+ case Paint.BIDI_DEFAULT_RTL:
+ return true;
+ default:
+ return false;
+ }
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
index 52b8f34..973fa0e 100644
--- a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
@@ -16,7 +16,10 @@
package android.text;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import com.ibm.icu.text.Bidi;
/**
@@ -29,9 +32,29 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
public class AndroidBidi_Delegate {
@LayoutlibDelegate
- /*package*/ static int runBidi(int dir, char[] chs, byte[] chInfo, int n, boolean haveInfo) {
- // return the equivalent of Layout.DIR_LEFT_TO_RIGHT
- // TODO: actually figure the direction.
- return 0;
+ /*package*/ static int runBidi(int dir, char[] chars, byte[] charInfo, int count,
+ boolean haveInfo) {
+
+ switch (dir) {
+ case 0: // Layout.DIR_REQUEST_LTR
+ case 1: // Layout.DIR_REQUEST_RTL
+ break; // No change.
+ case -1:
+ dir = Bidi.LEVEL_DEFAULT_LTR;
+ break;
+ case -2:
+ dir = Bidi.LEVEL_DEFAULT_RTL;
+ break;
+ default:
+ // Invalid code. Log error, assume LEVEL_DEFAULT_LTR and continue.
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Invalid direction flag", null);
+ dir = Bidi.LEVEL_DEFAULT_LTR;
+ }
+ Bidi bidi = new Bidi(chars, 0, null, 0, count, dir);
+ if (charInfo != null) {
+ for (int i = 0; i < count; ++i)
+ charInfo[i] = bidi.getLevelAt(i);
+ }
+ return bidi.getParaLevel();
}
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 434b131..fd153af 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -49,15 +49,13 @@ public class IWindowManagerImpl implements IWindowManager {
private final Configuration mConfig;
private final DisplayMetrics mMetrics;
private final int mRotation;
- private final boolean mHasSystemNavBar;
private final boolean mHasNavigationBar;
public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation,
- boolean hasSystemNavBar, boolean hasNavigationBar) {
+ boolean hasNavigationBar) {
mConfig = config;
mMetrics = metrics;
mRotation = rotation;
- mHasSystemNavBar = hasSystemNavBar;
mHasNavigationBar = hasNavigationBar;
}
@@ -79,16 +77,11 @@ public class IWindowManagerImpl implements IWindowManager {
return mHasNavigationBar;
}
- @Override
- public boolean hasSystemNavBar() throws RemoteException {
- return mHasSystemNavBar;
- }
-
// ---- unused implementation of IWindowManager ----
@Override
- public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4,
- boolean arg5)
+ public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4,
+ boolean arg5, boolean arg6, int arg7)
throws RemoteException {
// TODO Auto-generated method stub
@@ -211,24 +204,6 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void moveAppTokensToBottom(List<IBinder> arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void moveAppTokensToTop(List<IBinder> arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1)
throws RemoteException {
// TODO Auto-generated method stub
@@ -291,8 +266,8 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public Bitmap screenshotApplications(IBinder arg0, int displayId, int arg1, int arg2)
- throws RemoteException {
+ public Bitmap screenshotApplications(IBinder arg0, int displayId, int arg1,
+ int arg2, boolean arg3) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
@@ -322,7 +297,7 @@ public class IWindowManagerImpl implements IWindowManager {
@Override
public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
- CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
+ CharSequence arg4, int arg5, int arg6, int arg7, int arg8, IBinder arg9, boolean arg10)
throws RemoteException {
// TODO Auto-generated method stub
}
@@ -483,11 +458,6 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public void showAssistant() {
-
- }
-
- @Override
public IBinder getFocusedWindowToken() {
// TODO Auto-generated method stub
return null;
@@ -524,4 +494,8 @@ public class IWindowManagerImpl implements IWindowManager {
// TODO Auto-generated method stub
return false;
}
+
+ @Override
+ public void setTouchExplorationEnabled(boolean enabled) {
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java
index 3b66188..202f204 100644
--- a/tools/layoutlib/bridge/src/android/webkit/WebView.java
+++ b/tools/layoutlib/bridge/src/android/webkit/WebView.java
@@ -99,14 +99,6 @@ public class WebView extends MockView {
public static void disablePlatformNotifications() {
}
- public WebBackForwardList saveState(Bundle outState) {
- return null;
- }
-
- public WebBackForwardList restoreState(Bundle inState) {
- return null;
- }
-
public void loadUrl(String url) {
}
@@ -213,10 +205,6 @@ public class WebView extends MockView {
public void clearSslPreferences() {
}
- public WebBackForwardList copyBackForwardList() {
- return null;
- }
-
public static String findAddress(String addr) {
return null;
}
@@ -236,10 +224,6 @@ public class WebView extends MockView {
public void addJavascriptInterface(Object obj, String interfaceName) {
}
- public WebSettings getSettings() {
- return null;
- }
-
public View getZoomControls() {
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 42257c5..ab4be71 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -35,6 +35,7 @@ import com.android.resources.ResourceType;
import com.android.tools.layoutlib.create.MethodAdapter;
import com.android.tools.layoutlib.create.OverrideMethod;
import com.android.util.Pair;
+import com.ibm.icu.util.ULocale;
import android.content.res.BridgeAssetManager;
import android.graphics.Bitmap;
@@ -64,6 +65,8 @@ import java.util.concurrent.locks.ReentrantLock;
*/
public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
+ private static final String ICU_LOCALE_DIRECTION_RTL = "right-to-left";
+
public static class StaticMethodNotImplementedException extends RuntimeException {
private static final long serialVersionUID = 1L;
@@ -211,7 +214,8 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
Capability.ANIMATED_VIEW_MANIPULATION,
Capability.ADAPTER_BINDING,
Capability.EXTENDED_VIEWINFO,
- Capability.FIXED_SCALABLE_NINE_PATCH);
+ Capability.FIXED_SCALABLE_NINE_PATCH,
+ Capability.RTL);
BridgeAssetManager.initSystem();
@@ -411,6 +415,20 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
throw new IllegalArgumentException("viewObject is not a View");
}
+ @Override
+ public boolean isRtl(String locale) {
+ return isLocaleRtl(locale);
+ }
+
+ public static boolean isLocaleRtl(String locale) {
+ if (locale == null) {
+ locale = "";
+ }
+ ULocale uLocale = new ULocale(locale);
+ return uLocale.getCharacterOrientation().equals(ICU_LOCALE_DIRECTION_RTL) ?
+ true : false;
+ }
+
/**
* Returns the lock for the bridge
*/
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
index 4aea38f..01740b1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
@@ -81,14 +81,16 @@ public final class BridgeContentProvider implements IContentProvider {
}
@Override
- public AssetFileDescriptor openAssetFile(String callingPackage, Uri arg0, String arg1)
+ public AssetFileDescriptor openAssetFile(
+ String callingPackage, Uri arg0, String arg1, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
// TODO Auto-generated method stub
return null;
}
@Override
- public ParcelFileDescriptor openFile(String callingPackage, Uri arg0, String arg1)
+ public ParcelFileDescriptor openFile(
+ String callingPackage, Uri arg0, String arg1, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
// TODO Auto-generated method stub
return null;
@@ -122,7 +124,7 @@ public final class BridgeContentProvider implements IContentProvider {
@Override
public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri arg0, String arg1,
- Bundle arg2) throws RemoteException, FileNotFoundException {
+ Bundle arg2, ICancellationSignal signal) throws RemoteException, FileNotFoundException {
// TODO Auto-generated method stub
return null;
}
@@ -132,4 +134,14 @@ public final class BridgeContentProvider implements IContentProvider {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException {
+ return null;
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 21bef1c..b9294ab 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -67,8 +67,8 @@ import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.BridgeInflater;
-import android.view.CompatibilityInfoHolder;
import android.view.Display;
+import android.view.DisplayAdjustments;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -132,7 +132,8 @@ public final class BridgeContext extends Context {
RenderResources renderResources,
IProjectCallback projectCallback,
Configuration config,
- int targetSdkVersion) {
+ int targetSdkVersion,
+ boolean hasRtlSupport) {
mProjectKey = projectKey;
mMetrics = metrics;
mProjectCallback = projectCallback;
@@ -142,6 +143,9 @@ public final class BridgeContext extends Context {
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.targetSdkVersion = targetSdkVersion;
+ if (hasRtlSupport) {
+ mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL;
+ }
mWindowManager = new WindowManagerImpl(mMetrics);
}
@@ -1086,6 +1090,12 @@ public final class BridgeContext extends Context {
}
@Override
+ public String getOpPackageName() {
+ // pass
+ return null;
+ }
+
+ @Override
public ApplicationInfo getApplicationInfo() {
return mApplicationInfo;
}
@@ -1394,7 +1404,7 @@ public final class BridgeContext extends Context {
}
@Override
- public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+ public DisplayAdjustments getDisplayAdjustments(int displayId) {
// pass
return null;
}
@@ -1406,4 +1416,22 @@ public final class BridgeContext extends Context {
public int getUserId() {
return 0; // not used
}
+
+ @Override
+ public File[] getExternalFilesDirs(String type) {
+ // pass
+ return new File[0];
+ }
+
+ @Override
+ public File[] getObbDirs() {
+ // pass
+ return new File[0];
+ }
+
+ @Override
+ public File[] getExternalCacheDirs() {
+ // pass
+ return new File[0];
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index d6abbaa..3cf5ed5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -63,7 +63,7 @@ public class BridgeIInputMethodManager implements IInputMethodManager {
}
@Override
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo arg0,
+ public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String arg0,
boolean arg1) throws RemoteException {
// TODO Auto-generated method stub
return null;
@@ -203,6 +203,12 @@ public class BridgeIInputMethodManager implements IInputMethodManager {
}
@Override
+ public boolean shouldOfferSwitchingToNextInputMethod(IBinder arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
public void updateStatusIcon(IBinder arg0, String arg1, int arg2) throws RemoteException {
// TODO Auto-generated method stub
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 1ccbc40..a8b58aa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -39,7 +39,13 @@ public class BridgePowerManager implements IPowerManager {
}
@Override
- public void acquireWakeLock(IBinder arg0, int arg1, String arg2, WorkSource arg3)
+ public void acquireWakeLock(IBinder arg0, int arg1, String arg2, String arg2_5, WorkSource arg3)
+ throws RemoteException {
+ // pass for now.
+ }
+
+ @Override
+ public void acquireWakeLockWithUid(IBinder arg0, int arg1, String arg2, String arg2_5, int arg3)
throws RemoteException {
// pass for now.
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index ea9d8d9..17b0eb6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -25,6 +25,7 @@ import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.layoutlib.bridge.impl.ResourceHelper;
import com.android.resources.Density;
+import com.android.resources.LayoutDirection;
import com.android.resources.ResourceType;
import org.xmlpull.v1.XmlPullParser;
@@ -86,38 +87,53 @@ abstract class CustomBar extends LinearLayout {
}
}
- private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut,
- boolean tryOtherDensities) {
+ private InputStream getIcon(String iconName, Density[] densityInOut, LayoutDirection direction,
+ String[] pathOut, boolean tryOtherDensities) {
// current density
Density density = densityInOut[0];
// bitmap url relative to this class
- pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName;
+ if (direction != null) {
+ pathOut[0] = "/bars/" + direction.getResourceValue() + "-" + density.getResourceValue()
+ + "/" + iconName;
+ } else {
+ pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName;
+ }
InputStream stream = getClass().getResourceAsStream(pathOut[0]);
if (stream == null && tryOtherDensities) {
for (Density d : Density.values()) {
if (d != density) {
densityInOut[0] = d;
- stream = getIcon(iconName, densityInOut, pathOut, false /*tryOtherDensities*/);
+ stream = getIcon(iconName, densityInOut, direction, pathOut,
+ false /*tryOtherDensities*/);
if (stream != null) {
return stream;
}
}
}
+ // couldn't find resource with direction qualifier. try without.
+ if (direction != null) {
+ return getIcon(iconName, densityInOut, null, pathOut, true);
+ }
}
return stream;
}
protected void loadIcon(int index, String iconName, Density density) {
+ loadIcon(index, iconName, density, false);
+ }
+
+ protected void loadIcon(int index, String iconName, Density density, boolean isRtl) {
View child = getChildAt(index);
if (child instanceof ImageView) {
ImageView imageView = (ImageView) child;
String[] pathOut = new String[1];
Density[] densityInOut = new Density[] { density };
- InputStream stream = getIcon(iconName, densityInOut, pathOut,
+ LayoutDirection dir = isRtl ? LayoutDirection.RTL : LayoutDirection.LTR;
+ InputStream stream = getIcon(iconName, densityInOut, dir, pathOut,
true /*tryOtherDensities*/);
density = densityInOut[0];
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index cc90d6b..84e676e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -17,6 +17,7 @@
package com.android.layoutlib.bridge.bars;
import com.android.resources.Density;
+import com.android.layoutlib.bridge.Bridge;
import org.xmlpull.v1.XmlPullParserException;
@@ -26,7 +27,8 @@ import android.widget.TextView;
public class NavigationBar extends CustomBar {
- public NavigationBar(Context context, Density density, int orientation) throws XmlPullParserException {
+ public NavigationBar(Context context, Density density, int orientation, boolean isRtl,
+ boolean rtlEnabled) throws XmlPullParserException {
super(context, density, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml");
setBackgroundColor(0xFF000000);
@@ -37,14 +39,15 @@ public class NavigationBar extends CustomBar {
// 0 is a spacer.
int back = 1;
int recent = 3;
- if (orientation == LinearLayout.VERTICAL) {
+ if (orientation == LinearLayout.VERTICAL || (isRtl && !rtlEnabled)) {
+ // If RTL is enabled, then layoutlib mirrors the layout for us.
back = 3;
recent = 1;
}
- loadIcon(back, "ic_sysbar_back.png", density);
- loadIcon(2, "ic_sysbar_home.png", density);
- loadIcon(recent, "ic_sysbar_recent.png", density);
+ loadIcon(back, "ic_sysbar_back.png", density, isRtl);
+ loadIcon(2, "ic_sysbar_home.png", density, isRtl);
+ loadIcon(recent, "ic_sysbar_recent.png", density, isRtl);
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 5c08412..baa956d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -30,7 +30,10 @@ import android.widget.TextView;
public class StatusBar extends CustomBar {
- public StatusBar(Context context, Density density) throws XmlPullParserException {
+ public StatusBar(Context context, Density density, int direction, boolean RtlEnabled)
+ throws XmlPullParserException {
+ // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar.
+
super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml");
// FIXME: use FILL_H?
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
index 081ce67..108b651 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
@@ -52,6 +52,8 @@ public final class FontLoader {
private static final String NODE_NAME = "name";
private static final String NODE_FILE = "file";
+ private static final String ATTRIBUTE_VARIANT = "variant";
+ private static final String ATTRIBUTE_VALUE_ELEGANT = "elegant";
private static final String FONT_SUFFIX_NONE = ".ttf";
private static final String FONT_SUFFIX_REGULAR = "-Regular.ttf";
private static final String FONT_SUFFIX_BOLD = "-Bold.ttf";
@@ -189,6 +191,7 @@ public final class FontLoader {
private FontInfo mFontInfo = null;
private final StringBuilder mBuilder = new StringBuilder();
private List<FontInfo> mFontList = new ArrayList<FontInfo>();
+ private boolean isCompactFont = true;
private FontHandler(String osFontsLocation) {
super();
@@ -209,8 +212,21 @@ public final class FontLoader {
mFontList = new ArrayList<FontInfo>();
} else if (NODE_FAMILY.equals(localName)) {
if (mFontList != null) {
+ mFontInfo = null;
+ }
+ } else if (NODE_NAME.equals(localName)) {
+ if (mFontList != null && mFontInfo == null) {
+ mFontInfo = new FontInfo();
+ }
+ } else if (NODE_FILE.equals(localName)) {
+ if (mFontList != null && mFontInfo == null) {
mFontInfo = new FontInfo();
}
+ if (ATTRIBUTE_VALUE_ELEGANT.equals(attributes.getValue(ATTRIBUTE_VARIANT))) {
+ isCompactFont = false;
+ } else {
+ isCompactFont = true;
+ }
}
mBuilder.setLength(0);
@@ -223,7 +239,9 @@ public final class FontLoader {
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
- mBuilder.append(ch, start, length);
+ if (isCompactFont) {
+ mBuilder.append(ch, start, length);
+ }
}
/* (non-Javadoc)
@@ -259,7 +277,7 @@ public final class FontLoader {
}
} else if (NODE_FILE.equals(localName)) {
// handle a new file for an existing Font Info
- if (mFontInfo != null) {
+ if (isCompactFont && mFontInfo != null) {
String fileName = trimXmlWhitespaces(mBuilder.toString());
Font font = getFont(fileName);
if (font != null) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index b909bec..87047b3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -121,7 +121,8 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
// build the context
mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
- mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion());
+ mParams.getProjectCallback(), getConfiguration(), mParams.getTargetSdkVersion(),
+ mParams.isRtlSupported());
setUp();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index c14af4a..57771e3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -192,11 +192,10 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
findNavigationBar(resources, metrics);
// FIXME: find those out, and possibly add them to the render params
- boolean hasSystemNavBar = true;
boolean hasNavigationBar = true;
IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
metrics, Surface.ROTATION_0,
- hasSystemNavBar, hasNavigationBar);
+ hasNavigationBar);
WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
// build the inflater and parser.
@@ -225,13 +224,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
SessionParams params = getParams();
HardwareConfig hardwareConfig = params.getHardwareConfig();
BridgeContext context = getContext();
-
+ boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
+ int direction = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
// the view group that receives the window background.
ViewGroup backgroundView = null;
if (mWindowIsFloating || params.isForceNoDecor()) {
backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
+ mViewRoot.setLayoutDirection(direction);
} else {
if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
/*
@@ -253,12 +254,14 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
the bottom
*/
LinearLayout topLayout = new LinearLayout(context);
+ topLayout.setLayoutDirection(direction);
mViewRoot = topLayout;
topLayout.setOrientation(LinearLayout.HORIZONTAL);
try {
NavigationBar navigationBar = new NavigationBar(context,
- hardwareConfig.getDensity(), LinearLayout.VERTICAL);
+ hardwareConfig.getDensity(), LinearLayout.VERTICAL, isRtl,
+ params.isRtlSupported());
navigationBar.setLayoutParams(
new LinearLayout.LayoutParams(
mNavigationBarSize,
@@ -290,6 +293,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
LinearLayout topLayout = new LinearLayout(context);
topLayout.setOrientation(LinearLayout.VERTICAL);
+ topLayout.setLayoutDirection(direction);
// if we don't already have a view root this is it
if (mViewRoot == null) {
mViewRoot = topLayout;
@@ -301,13 +305,22 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// this is the case of soft buttons + vertical bar.
// this top layout is the first layout in the horizontal layout. see above)
- mViewRoot.addView(topLayout, 0);
+ if (isRtl && params.isRtlSupported()) {
+ // If RTL is enabled, layoutlib will mirror the layouts. So, add the
+ // topLayout to the right of Navigation Bar and layoutlib will draw it
+ // to the left.
+ mViewRoot.addView(topLayout);
+ } else {
+ // Add the top layout to the left of the Navigation Bar.
+ mViewRoot.addView(topLayout, 0);
+ }
}
if (mStatusBarSize > 0) {
// system bar
try {
- StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity());
+ StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity(),
+ direction, params.isRtlSupported());
systemBar.setLayoutParams(
new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, mStatusBarSize));
@@ -366,7 +379,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// system bar
try {
NavigationBar navigationBar = new NavigationBar(context,
- hardwareConfig.getDensity(), LinearLayout.HORIZONTAL);
+ hardwareConfig.getDensity(), LinearLayout.HORIZONTAL, isRtl,
+ params.isRtlSupported());
navigationBar.setLayoutParams(
new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, mNavigationBarSize));
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
index e0414fe..6c998af 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/BaseAdapter.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2013 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.
@@ -16,7 +16,6 @@
package com.android.layoutlib.bridge.impl.binding;
-import com.android.ide.common.rendering.api.AdapterBinding;
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
@@ -27,7 +26,6 @@ import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.util.Pair;
-import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -35,124 +33,27 @@ import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.TextView;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
/**
- * Base adapter to do fake data binding in {@link AdapterView} objects.
+ * A Helper class to do fake data binding in {@link AdapterView} objects.
*/
-public class BaseAdapter {
-
- /**
- * This is the items provided by the adapter. They are dynamically generated.
- */
- protected final static class AdapterItem {
- private final DataBindingItem mItem;
- private final int mType;
- private final int mFullPosition;
- private final int mPositionPerType;
- private List<AdapterItem> mChildren;
-
- protected AdapterItem(DataBindingItem item, int type, int fullPosition,
- int positionPerType) {
- mItem = item;
- mType = type;
- mFullPosition = fullPosition;
- mPositionPerType = positionPerType;
- }
-
- void addChild(AdapterItem child) {
- if (mChildren == null) {
- mChildren = new ArrayList<AdapterItem>();
- }
-
- mChildren.add(child);
- }
-
- List<AdapterItem> getChildren() {
- if (mChildren != null) {
- return mChildren;
- }
-
- return Collections.emptyList();
- }
-
- int getType() {
- return mType;
- }
-
- int getFullPosition() {
- return mFullPosition;
- }
-
- int getPositionPerType() {
- return mPositionPerType;
- }
-
- DataBindingItem getDataBindingItem() {
- return mItem;
- }
- }
-
- private final AdapterBinding mBinding;
- private final IProjectCallback mCallback;
- private final ResourceReference mAdapterRef;
- private boolean mSkipCallbackParser = false;
-
- protected final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
-
- protected BaseAdapter(ResourceReference adapterRef, AdapterBinding binding,
- IProjectCallback callback) {
- mAdapterRef = adapterRef;
- mBinding = binding;
- mCallback = callback;
- }
-
- // ------- Some Adapter method used by all children classes.
-
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- public boolean hasStableIds() {
- return true;
- }
-
- public boolean isEmpty() {
- return mItems.size() == 0;
- }
-
- public void registerDataSetObserver(DataSetObserver observer) {
- // pass
- }
-
- public void unregisterDataSetObserver(DataSetObserver observer) {
- // pass
- }
-
- // -------
-
-
- protected AdapterBinding getBinding() {
- return mBinding;
- }
+@SuppressWarnings("deprecation")
+public class AdapterHelper {
- protected View getView(AdapterItem item, AdapterItem parentItem, View convertView,
- ViewGroup parent) {
+ static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
+ IProjectCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
// we don't care about recycling here because we never scroll.
DataBindingItem dataBindingItem = item.getDataBindingItem();
BridgeContext context = RenderAction.getCurrentContext();
Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(),
- parent, false /*attachToRoot*/, mSkipCallbackParser);
+ parent, false /*attachToRoot*/, skipCallbackParser);
View view = pair.getFirst();
- mSkipCallbackParser |= pair.getSecond();
+ skipCallbackParser |= pair.getSecond();
if (view != null) {
- fillView(context, view, item, parentItem);
+ fillView(context, view, item, parentItem, callback, adapterRef);
} else {
// create a text view to display an error.
TextView tv = new TextView(context);
@@ -160,16 +61,16 @@ public class BaseAdapter {
view = tv;
}
- return view;
+ return Pair.of(view, skipCallbackParser);
}
- private void fillView(BridgeContext context, View view, AdapterItem item,
- AdapterItem parentItem) {
+ private static void fillView(BridgeContext context, View view, AdapterItem item,
+ AdapterItem parentItem, IProjectCallback callback, ResourceReference adapterRef) {
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
final int count = group.getChildCount();
for (int i = 0 ; i < count ; i++) {
- fillView(context, group.getChildAt(i), item, parentItem);
+ fillView(context, group.getChildAt(i), item, parentItem, callback, adapterRef);
}
} else {
int id = view.getId();
@@ -184,8 +85,8 @@ public class BaseAdapter {
if (view instanceof TextView) {
TextView tv = (TextView) view;
- Object value = mCallback.getAdapterItemValue(
- mAdapterRef, context.getViewKey(view),
+ Object value = callback.getAdapterItemValue(
+ adapterRef, context.getViewKey(view),
item.getDataBindingItem().getViewReference(),
fullPosition, positionPerType,
fullParentPosition, parentPositionPerType,
@@ -204,8 +105,8 @@ public class BaseAdapter {
if (view instanceof Checkable) {
Checkable cb = (Checkable) view;
- Object value = mCallback.getAdapterItemValue(
- mAdapterRef, context.getViewKey(view),
+ Object value = callback.getAdapterItemValue(
+ adapterRef, context.getViewKey(view),
item.getDataBindingItem().getViewReference(),
fullPosition, positionPerType,
fullParentPosition, parentPositionPerType,
@@ -224,8 +125,8 @@ public class BaseAdapter {
if (view instanceof ImageView) {
ImageView iv = (ImageView) view;
- Object value = mCallback.getAdapterItemValue(
- mAdapterRef, context.getViewKey(view),
+ Object value = callback.getAdapterItemValue(
+ adapterRef, context.getViewKey(view),
item.getDataBindingItem().getViewReference(),
fullPosition, positionPerType,
fullParentPosition, parentPositionPerType,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java
new file mode 100644
index 0000000..8e28dba
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 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.layoutlib.bridge.impl.binding;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import com.android.ide.common.rendering.api.DataBindingItem;
+
+/**
+ * This is the items provided by the adapter. They are dynamically generated.
+ */
+final class AdapterItem {
+ private final DataBindingItem mItem;
+ private final int mType;
+ private final int mFullPosition;
+ private final int mPositionPerType;
+ private List<AdapterItem> mChildren;
+
+ protected AdapterItem(DataBindingItem item, int type, int fullPosition,
+ int positionPerType) {
+ mItem = item;
+ mType = type;
+ mFullPosition = fullPosition;
+ mPositionPerType = positionPerType;
+ }
+
+ void addChild(AdapterItem child) {
+ if (mChildren == null) {
+ mChildren = new ArrayList<AdapterItem>();
+ }
+
+ mChildren.add(child);
+ }
+
+ List<AdapterItem> getChildren() {
+ if (mChildren != null) {
+ return mChildren;
+ }
+
+ return Collections.emptyList();
+ }
+
+ int getType() {
+ return mType;
+ }
+
+ int getFullPosition() {
+ return mFullPosition;
+ }
+
+ int getPositionPerType() {
+ return mPositionPerType;
+ }
+
+ DataBindingItem getDataBindingItem() {
+ return mItem;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java
index 22570b9..9a13f5a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java
@@ -20,10 +20,12 @@ import com.android.ide.common.rendering.api.AdapterBinding;
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.ResourceReference;
+import com.android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
+import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.SpinnerAdapter;
@@ -35,17 +37,23 @@ import java.util.List;
* and {@link SpinnerAdapter}.
*
*/
-public class FakeAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter {
+@SuppressWarnings("deprecation")
+public class FakeAdapter extends BaseAdapter {
// don't use a set because the order is important.
private final List<ResourceReference> mTypes = new ArrayList<ResourceReference>();
+ private final IProjectCallback mCallback;
+ private final ResourceReference mAdapterRef;
+ private final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
+ private boolean mSkipCallbackParser = false;
public FakeAdapter(ResourceReference adapterRef, AdapterBinding binding,
IProjectCallback callback) {
- super(adapterRef, binding, callback);
+ mAdapterRef = adapterRef;
+ mCallback = callback;
- final int repeatCount = getBinding().getRepeatCount();
- final int itemCount = getBinding().getItemCount();
+ final int repeatCount = binding.getRepeatCount();
+ final int itemCount = binding.getItemCount();
// Need an array to count for each type.
// This is likely too big, but is the max it can be.
@@ -54,7 +62,7 @@ public class FakeAdapter extends BaseAdapter implements ListAdapter, SpinnerAdap
// We put several repeating sets.
for (int r = 0 ; r < repeatCount ; r++) {
// loop on the type of list items, and add however many for each type.
- for (DataBindingItem dataBindingItem : getBinding()) {
+ for (DataBindingItem dataBindingItem : binding) {
ResourceReference viewRef = dataBindingItem.getViewReference();
int typeIndex = mTypes.indexOf(viewRef);
if (typeIndex == -1) {
@@ -103,7 +111,11 @@ public class FakeAdapter extends BaseAdapter implements ListAdapter, SpinnerAdap
public View getView(int position, View convertView, ViewGroup parent) {
// we don't care about recycling here because we never scroll.
AdapterItem item = mItems.get(position);
- return getView(item, null /*parentGroup*/, convertView, parent);
+ Pair<View, Boolean> pair = AdapterHelper.getView(item, null /*parentGroup*/, parent,
+ mCallback, mAdapterRef, mSkipCallbackParser);
+ mSkipCallbackParser = pair.getSecond();
+ return pair.getFirst();
+
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java
index 199e040..e539579 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java
@@ -20,7 +20,9 @@ import com.android.ide.common.rendering.api.AdapterBinding;
import com.android.ide.common.rendering.api.DataBindingItem;
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.ResourceReference;
+import com.android.util.Pair;
+import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListAdapter;
@@ -29,8 +31,14 @@ import android.widget.HeterogeneousExpandableList;
import java.util.ArrayList;
import java.util.List;
-public class FakeExpandableAdapter extends BaseAdapter implements ExpandableListAdapter,
- HeterogeneousExpandableList {
+@SuppressWarnings("deprecation")
+public class FakeExpandableAdapter implements ExpandableListAdapter, HeterogeneousExpandableList {
+
+ private final IProjectCallback mCallback;
+ private final ResourceReference mAdapterRef;
+ private boolean mSkipCallbackParser = false;
+
+ protected final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
// don't use a set because the order is important.
private final List<ResourceReference> mGroupTypes = new ArrayList<ResourceReference>();
@@ -38,7 +46,8 @@ public class FakeExpandableAdapter extends BaseAdapter implements ExpandableList
public FakeExpandableAdapter(ResourceReference adapterRef, AdapterBinding binding,
IProjectCallback callback) {
- super(adapterRef, binding, callback);
+ mAdapterRef = adapterRef;
+ mCallback = callback;
createItems(binding, binding.getItemCount(), binding.getRepeatCount(), mGroupTypes, 1);
}
@@ -125,7 +134,10 @@ public class FakeExpandableAdapter extends BaseAdapter implements ExpandableList
ViewGroup parent) {
// we don't care about recycling here because we never scroll.
AdapterItem item = mItems.get(groupPosition);
- return getView(item, null /*parentItem*/, convertView, parent);
+ Pair<View, Boolean> pair = AdapterHelper.getView(item, null /*parentItem*/, parent,
+ mCallback, mAdapterRef, mSkipCallbackParser);
+ mSkipCallbackParser = pair.getSecond();
+ return pair.getFirst();
}
@Override
@@ -134,7 +146,10 @@ public class FakeExpandableAdapter extends BaseAdapter implements ExpandableList
// we don't care about recycling here because we never scroll.
AdapterItem parentItem = mItems.get(groupPosition);
AdapterItem item = getChildItem(groupPosition, childPosition);
- return getView(item, parentItem, convertView, parent);
+ Pair<View, Boolean> pair = AdapterHelper.getView(item, parentItem, parent, mCallback,
+ mAdapterRef, mSkipCallbackParser);
+ mSkipCallbackParser = pair.getSecond();
+ return pair.getFirst();
}
@Override
@@ -172,6 +187,31 @@ public class FakeExpandableAdapter extends BaseAdapter implements ExpandableList
// pass
}
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ // pass
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ // pass
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mItems.isEmpty();
+ }
+
// ---- HeterogeneousExpandableList
@Override
diff --git a/tools/obbtool/Android.mk b/tools/obbtool/Android.mk
index ad8de69..9ff56d6 100644
--- a/tools/obbtool/Android.mk
+++ b/tools/obbtool/Android.mk
@@ -18,8 +18,8 @@ LOCAL_CFLAGS := -Wall -Werror
#LOCAL_C_INCLUDES +=
LOCAL_STATIC_LIBRARIES := \
- libutils \
libandroidfw \
+ libutils \
libcutils \
liblog
diff --git a/tools/preload/Policy.java b/tools/preload/Policy.java
index ca0291b..af46820 100644
--- a/tools/preload/Policy.java
+++ b/tools/preload/Policy.java
@@ -81,8 +81,9 @@ public class Policy {
return SERVICES.contains(processName);
}
- /**Reports if the given class should be preloaded. */
+ /** Reports if the given class should be preloaded. */
public static boolean isPreloadable(LoadedClass clazz) {
- return clazz.systemClass && !EXCLUDED_CLASSES.contains(clazz.name);
+ return clazz.systemClass && !EXCLUDED_CLASSES.contains(clazz.name)
+ && !clazz.name.endsWith("$NoPreloadHolder");
}
}
diff --git a/tools/validatekeymaps/Android.mk b/tools/validatekeymaps/Android.mk
index 90fbc08..9af721d 100644
--- a/tools/validatekeymaps/Android.mk
+++ b/tools/validatekeymaps/Android.mk
@@ -15,10 +15,8 @@ LOCAL_SRC_FILES := \
LOCAL_CFLAGS := -Wall -Werror
-#LOCAL_C_INCLUDES +=
-
LOCAL_STATIC_LIBRARIES := \
- libandroidfw \
+ libinput \
libutils \
libcutils \
liblog
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index 91e4fda..5b45c55 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include <androidfw/KeyCharacterMap.h>
-#include <androidfw/KeyLayoutMap.h>
-#include <androidfw/VirtualKeyMap.h>
+#include <input/KeyCharacterMap.h>
+#include <input/KeyLayoutMap.h>
+#include <input/VirtualKeyMap.h>
#include <utils/PropertyMap.h>
#include <utils/String8.h>