diff options
52 files changed, 485 insertions, 140 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk index ffdac4e..c6f6a62 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -189,6 +189,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/servic $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/IMedia*) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/view/IMagnificationCallbacks*) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST diff --git a/api/current.txt b/api/current.txt index a768e43..3573e6d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9736,9 +9736,13 @@ package android.graphics { method public int save(); method public int save(int); method public int saveLayer(android.graphics.RectF, android.graphics.Paint, int); + method public int saveLayer(android.graphics.RectF, android.graphics.Paint); method public int saveLayer(float, float, float, float, android.graphics.Paint, int); + method public int saveLayer(float, float, float, float, android.graphics.Paint); method public int saveLayerAlpha(android.graphics.RectF, int, int); + method public int saveLayerAlpha(android.graphics.RectF, int); method public int saveLayerAlpha(float, float, float, float, int, int); + method public int saveLayerAlpha(float, float, float, float, int); method public void scale(float, float); method public final void scale(float, float, float, float); method public void setBitmap(android.graphics.Bitmap); diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 63e15a9..19be2c8 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -487,7 +487,7 @@ public class Build { * new changes in behavior:</p> * <ul> * <li> {@link android.content.Context#bindService Context.bindService} now - * requires an explicit Intent, and will throw an exception if given an explicit + * requires an explicit Intent, and will throw an exception if given an implicit * Intent.</li> * </ul> */ diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index e96398a..e98a26b 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -42,6 +42,7 @@ public class Environment { private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE"; private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT"; private static final String ENV_OEM_ROOT = "OEM_ROOT"; + private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT"; /** {@hide} */ public static final String DIR_ANDROID = "Android"; @@ -57,6 +58,7 @@ public class Environment { private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system"); private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem"); + private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor"); private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media"); private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull( @@ -225,6 +227,15 @@ public class Environment { } /** + * Return root directory of the "vendor" partition that holds vendor-provided + * software that should persist across simple reflashing of the "system" partition. + * @hide + */ + public static File getVendorDirectory() { + return DIR_VENDOR_ROOT; + } + + /** * Gets the system directory available for secure storage. * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system). * Otherwise, it returns the unencrypted /data/system directory. diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java index 325b2e6..ff16f6c 100644 --- a/core/java/android/preference/PreferenceFragment.java +++ b/core/java/android/preference/PreferenceFragment.java @@ -329,6 +329,11 @@ public abstract class PreferenceFragment extends Fragment implements if (preferenceScreen != null) { preferenceScreen.bind(getListView()); } + onBindPreferences(); + } + + /** @hide */ + protected void onBindPreferences() { } /** @hide */ diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java index 9b41ff0..381a5f0 100644 --- a/core/java/android/preference/PreferenceGroupAdapter.java +++ b/core/java/android/preference/PreferenceGroupAdapter.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Handler; import android.preference.Preference.OnPreferenceChangeInternalListener; @@ -243,6 +242,7 @@ public class PreferenceGroupAdapter extends BaseAdapter if (position == mHighlightedPosition && mHighlightedDrawable != null) { result.setBackgroundDrawable(mHighlightedDrawable); } + result.setTag(preference.getKey()); return result; } diff --git a/data/keyboards/Vendor_1949_Product_0401.kl b/data/keyboards/Vendor_1949_Product_0401.kl new file mode 100644 index 0000000..ab24bcd --- /dev/null +++ b/data/keyboards/Vendor_1949_Product_0401.kl @@ -0,0 +1,27 @@ +# Copyright (C) 2014 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. + +# Amazon Fire TV remote + +key 103 DPAD_UP +key 108 DPAD_DOWN +key 105 DPAD_LEFT +key 106 DPAD_RIGHT +key 96 DPAD_CENTER +key 158 BACK +key 172 HOME +key 168 MEDIA_REWIND +key 208 MEDIA_FAST_FORWARD +key 164 MEDIA_PLAY_PAUSE +key 217 ASSIST diff --git a/docs/html/design/media/dialogs_examples.png b/docs/html/design/media/dialogs_examples.png Binary files differindex c136476..6ffcee2 100644 --- a/docs/html/design/media/dialogs_examples.png +++ b/docs/html/design/media/dialogs_examples.png diff --git a/docs/html/design/media/navigation_drawer_titles_icons.png b/docs/html/design/media/navigation_drawer_titles_icons.png Binary files differindex 7cf1e0c..902a72d 100644 --- a/docs/html/design/media/navigation_drawer_titles_icons.png +++ b/docs/html/design/media/navigation_drawer_titles_icons.png diff --git a/docs/html/design/media/selection_adjusting_actions.png b/docs/html/design/media/selection_adjusting_actions.png Binary files differindex 0799b6b..32a7fec 100644 --- a/docs/html/design/media/selection_adjusting_actions.png +++ b/docs/html/design/media/selection_adjusting_actions.png diff --git a/docs/html/design/media/touch_feedback_communication.png b/docs/html/design/media/touch_feedback_communication.png Binary files differindex f8162d0..1d4a9dc 100644 --- a/docs/html/design/media/touch_feedback_communication.png +++ b/docs/html/design/media/touch_feedback_communication.png diff --git a/docs/html/design/media/ui_overview_notifications.png b/docs/html/design/media/ui_overview_notifications.png Binary files differindex 6043412..7975657 100644 --- a/docs/html/design/media/ui_overview_notifications.png +++ b/docs/html/design/media/ui_overview_notifications.png diff --git a/docs/html/images/activity_lifecycle.png b/docs/html/images/activity_lifecycle.png Binary files differindex 71ffe9f..879f51f 100644 --- a/docs/html/images/activity_lifecycle.png +++ b/docs/html/images/activity_lifecycle.png diff --git a/docs/html/images/admin/device-admin-activate-prompt.png b/docs/html/images/admin/device-admin-activate-prompt.png Binary files differindex 1ebe719..3786788 100644 --- a/docs/html/images/admin/device-admin-activate-prompt.png +++ b/docs/html/images/admin/device-admin-activate-prompt.png diff --git a/docs/html/images/axis_device.png b/docs/html/images/axis_device.png Binary files differindex dd9c23b..f1f666a 100644 --- a/docs/html/images/axis_device.png +++ b/docs/html/images/axis_device.png diff --git a/docs/html/images/developing/ddms-network.png b/docs/html/images/developing/ddms-network.png Binary files differindex 5bf4ce6..5aa1290 100644 --- a/docs/html/images/developing/ddms-network.png +++ b/docs/html/images/developing/ddms-network.png diff --git a/docs/html/images/developing/hv_device_window.png b/docs/html/images/developing/hv_device_window.png Binary files differindex d2a1ddc..2bb80a8 100644 --- a/docs/html/images/developing/hv_device_window.png +++ b/docs/html/images/developing/hv_device_window.png diff --git a/docs/html/images/efficient-downloads/mobile_radio_state_machine.png b/docs/html/images/efficient-downloads/mobile_radio_state_machine.png Binary files differindex 98e9398..e06608b 100644 --- a/docs/html/images/efficient-downloads/mobile_radio_state_machine.png +++ b/docs/html/images/efficient-downloads/mobile_radio_state_machine.png diff --git a/docs/html/images/fundamentals/fragments.png b/docs/html/images/fundamentals/fragments.png Binary files differindex 8abaeba..cb7204b 100644 --- a/docs/html/images/fundamentals/fragments.png +++ b/docs/html/images/fundamentals/fragments.png diff --git a/docs/html/images/opengl/ogl-triangle.png b/docs/html/images/opengl/ogl-triangle.png Binary files differindex 6fefe1f..66047ab 100644 --- a/docs/html/images/opengl/ogl-triangle.png +++ b/docs/html/images/opengl/ogl-triangle.png diff --git a/docs/html/images/publishing/publishing_preparing.png b/docs/html/images/publishing/publishing_preparing.png Binary files differindex 07fcc58..40c0ac6 100644 --- a/docs/html/images/publishing/publishing_preparing.png +++ b/docs/html/images/publishing/publishing_preparing.png diff --git a/docs/html/images/screens_support/compat-zoom-thumb.png b/docs/html/images/screens_support/compat-zoom-thumb.png Binary files differindex 9d76e20..244800b 100644 --- a/docs/html/images/screens_support/compat-zoom-thumb.png +++ b/docs/html/images/screens_support/compat-zoom-thumb.png diff --git a/docs/html/images/sdk_manager_packages.png b/docs/html/images/sdk_manager_packages.png Binary files differindex eddd80c..a0e8108 100644 --- a/docs/html/images/sdk_manager_packages.png +++ b/docs/html/images/sdk_manager_packages.png diff --git a/docs/html/images/tools/as-breakpointswindow.png b/docs/html/images/tools/as-breakpointswindow.png Binary files differindex e5ae19d..a40b459 100644 --- a/docs/html/images/tools/as-breakpointswindow.png +++ b/docs/html/images/tools/as-breakpointswindow.png diff --git a/docs/html/images/tools/as-buildvariants.png b/docs/html/images/tools/as-buildvariants.png Binary files differindex 8e05a1e..a245163 100644 --- a/docs/html/images/tools/as-buildvariants.png +++ b/docs/html/images/tools/as-buildvariants.png diff --git a/docs/html/images/tools/as-mainscreen.png b/docs/html/images/tools/as-mainscreen.png Binary files differindex 6f2bc3c..da399d7 100644 --- a/docs/html/images/tools/as-mainscreen.png +++ b/docs/html/images/tools/as-mainscreen.png diff --git a/docs/html/images/tools/as-theme-db.png b/docs/html/images/tools/as-theme-db.png Binary files differindex a9e34c7..beade0d 100644 --- a/docs/html/images/tools/as-theme-db.png +++ b/docs/html/images/tools/as-theme-db.png diff --git a/docs/html/images/tools/sdk-manager-support-libs.png b/docs/html/images/tools/sdk-manager-support-libs.png Binary files differindex a44f4bb..3796800 100644 --- a/docs/html/images/tools/sdk-manager-support-libs.png +++ b/docs/html/images/tools/sdk-manager-support-libs.png diff --git a/docs/html/images/training/app-navigation-multiple-sizes-multipane-good.png b/docs/html/images/training/app-navigation-multiple-sizes-multipane-good.png Binary files differindex 1a8766f..3588318 100644 --- a/docs/html/images/training/app-navigation-multiple-sizes-multipane-good.png +++ b/docs/html/images/training/app-navigation-multiple-sizes-multipane-good.png diff --git a/docs/html/images/training/basics/intent-chooser.png b/docs/html/images/training/basics/intent-chooser.png Binary files differindex 14b6c45..8a8d339 100644 --- a/docs/html/images/training/basics/intent-chooser.png +++ b/docs/html/images/training/basics/intent-chooser.png diff --git a/docs/html/images/training/basics/network-settings1.png b/docs/html/images/training/basics/network-settings1.png Binary files differindex 8395abc..9eaf207 100644 --- a/docs/html/images/training/basics/network-settings1.png +++ b/docs/html/images/training/basics/network-settings1.png diff --git a/docs/html/images/training/basics/network-settings2.png b/docs/html/images/training/basics/network-settings2.png Binary files differindex 4e02c09..5f4dc63 100644 --- a/docs/html/images/training/basics/network-settings2.png +++ b/docs/html/images/training/basics/network-settings2.png diff --git a/docs/html/images/training/firstapp/adt-new-activity.png b/docs/html/images/training/firstapp/adt-new-activity.png Binary files differindex 6d89e4b..2c32dcc 100644 --- a/docs/html/images/training/firstapp/adt-new-activity.png +++ b/docs/html/images/training/firstapp/adt-new-activity.png diff --git a/docs/html/images/ui/clipboard/copy_paste_framework.png b/docs/html/images/ui/clipboard/copy_paste_framework.png Binary files differindex 9409a5d..57facaa 100644 --- a/docs/html/images/ui/clipboard/copy_paste_framework.png +++ b/docs/html/images/ui/clipboard/copy_paste_framework.png diff --git a/docs/html/images/ui/dialog_checkboxes.png b/docs/html/images/ui/dialog_checkboxes.png Binary files differindex af84b6a..8f272e5 100644 --- a/docs/html/images/ui/dialog_checkboxes.png +++ b/docs/html/images/ui/dialog_checkboxes.png diff --git a/docs/html/resources/articles/images/inputmethod_lifecycle_image.png b/docs/html/resources/articles/images/inputmethod_lifecycle_image.png Binary files differindex a975aa7..5f7cf95 100644 --- a/docs/html/resources/articles/images/inputmethod_lifecycle_image.png +++ b/docs/html/resources/articles/images/inputmethod_lifecycle_image.png diff --git a/docs/html/resources/articles/images/spellcheck_lifecycle.png b/docs/html/resources/articles/images/spellcheck_lifecycle.png Binary files differindex 4349d63..00bd461 100644 --- a/docs/html/resources/articles/images/spellcheck_lifecycle.png +++ b/docs/html/resources/articles/images/spellcheck_lifecycle.png diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 1252ee2..f80ce28 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -168,21 +168,10 @@ public class Canvas { } /** - * Gets the native canvas pointer. - * - * @return The native pointer. - * - * @hide - */ - public long getNativeCanvas() { - return mNativeCanvas; - } - - /** * Returns null. - * + * * @deprecated This method is not supported and should not be invoked. - * + * * @hide */ @Deprecated @@ -233,14 +222,14 @@ public class Canvas { mBitmap = bitmap; } - + /** * Set the viewport dimensions if this canvas is GL based. If it is not, * this method is ignored and no exception is thrown. * * @param width The width of the viewport * @param height The height of the viewport - * + * * @hide */ public void setViewport(int width, int height) { @@ -389,7 +378,14 @@ public class Canvas { paint != null ? paint.mNativePaint : 0, saveFlags); } - + + /** + * Convenience for saveLayer(bounds, paint, {@link #ALL_SAVE_FLAG}) + */ + public int saveLayer(RectF bounds, Paint paint) { + return saveLayer(bounds, paint, ALL_SAVE_FLAG); + } + /** * Helper version of saveLayer() that takes 4 values rather than a RectF. */ @@ -401,6 +397,13 @@ public class Canvas { } /** + * Convenience for saveLayer(left, top, right, bottom, paint, {@link #ALL_SAVE_FLAG}) + */ + public int saveLayer(float left, float top, float right, float bottom, Paint paint) { + return saveLayer(left, top, right, bottom, paint, ALL_SAVE_FLAG); + } + + /** * This behaves the same as save(), but in addition it allocates an * offscreen bitmap. All drawing calls are directed there, and only when * the balancing call to restore() is made is that offscreen transfered to @@ -420,7 +423,14 @@ public class Canvas { alpha = Math.min(255, Math.max(0, alpha)); return native_saveLayerAlpha(mNativeCanvas, bounds, alpha, saveFlags); } - + + /** + * Convenience for saveLayerAlpha(bounds, alpha, {@link #ALL_SAVE_FLAG}) + */ + public int saveLayerAlpha(RectF bounds, int alpha) { + return saveLayerAlpha(bounds, alpha, ALL_SAVE_FLAG); + } + /** * Helper for saveLayerAlpha() that takes 4 values instead of a RectF. */ @@ -431,6 +441,13 @@ public class Canvas { } /** + * Helper for saveLayerAlpha(left, top, right, bottom, alpha, {@link #ALL_SAVE_FLAG}) + */ + public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha) { + return saveLayerAlpha(left, top, right, bottom, alpha, ALL_SAVE_FLAG); + } + + /** * This call balances a previous call to save(), and is used to remove all * modifications to the matrix/clip state since the last save call. It is * an error to call restore() more times than save() was called. diff --git a/packages/DefaultContainerService/Android.mk b/packages/DefaultContainerService/Android.mk index 9961168..0de2c1f 100644 --- a/packages/DefaultContainerService/Android.mk +++ b/packages/DefaultContainerService/Android.mk @@ -7,7 +7,7 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := DefaultContainerService -LOCAL_REQUIRED_MODULES := libdefcontainer_jni +LOCAL_JNI_SHARED_LIBRARIES := libdefcontainer_jni LOCAL_CERTIFICATE := platform diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk index d9566d5..79f8a1f 100644 --- a/packages/services/PacProcessor/Android.mk +++ b/packages/services/PacProcessor/Android.mk @@ -25,7 +25,9 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_PACKAGE_NAME := PacProcessor LOCAL_CERTIFICATE := platform -LOCAL_REQUIRED_MODULES := libjni_pacprocessor +LOCAL_JNI_SHARED_LIBRARIES := libjni_pacprocessor + +LOCAL_MULTILIB := 32 include $(BUILD_PACKAGE) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index df69a6e..702d9d2 100755 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4492,17 +4492,6 @@ public class PackageManagerService extends IPackageManager.Stub { // writer synchronized (mPackages) { - if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { - // Check all shared libraries and map to their actual file path. - // We only do this here for apps not on a system dir, because those - // are the only ones that can fail an install due to this. We - // will take care of the system apps by updating all of their - // library paths after the scan is done. - if (!updateSharedLibrariesLPw(pkg, null)) { - return null; - } - } - if (pkg.mSharedUserId != null) { suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true); if (suid == null) { @@ -4613,6 +4602,17 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } + if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { + // Check all shared libraries and map to their actual file path. + // We only do this here for apps not on a system dir, because those + // are the only ones that can fail an install due to this. We + // will take care of the system apps by updating all of their + // library paths after the scan is done. + if (!updateSharedLibrariesLPw(pkg, null)) { + return null; + } + } + if (mFoundPolicyFile) { SELinuxMMAC.assignSeinfoValue(pkg); } @@ -5420,6 +5420,37 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private String calculateApkRoot(final File codePath) { + final File codeRoot; + if (FileUtils.contains(Environment.getRootDirectory(), codePath)) { + codeRoot = Environment.getRootDirectory(); + } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) { + codeRoot = Environment.getRootDirectory(); + } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) { + codeRoot = Environment.getVendorDirectory(); + } else { + // Unrecognized code path; take its top real segment as the apk root: + // e.g. /something/app/blah.apk => /something + try { + File f = codePath.getCanonicalFile(); + File parent = f.getParentFile(); // non-null because codePath is a file + File tmp; + while ((tmp = parent.getParentFile()) != null) { + f = parent; + parent = tmp; + } + codeRoot = f; + Slog.w(TAG, "Unrecognized code path " + + codePath + " - using " + codeRoot); + } catch (IOException e) { + // Can't canonicalize the lib path -- shenanigans? + Slog.w(TAG, "Can't canonicalize code path " + codePath); + return Environment.getRootDirectory().getPath(); + } + } + return codeRoot.getPath(); + } + // This is the initial scan-time determination of how to handle a given // package for purposes of native library location. private void setInternalAppNativeLibraryPath(PackageParser.Package pkg, @@ -5431,11 +5462,10 @@ public class PackageManagerService extends IPackageManager.Stub { if (bundledApk) { // If "/system/lib64/apkname" exists, assume that is the per-package // native library directory to use; otherwise use "/system/lib/apkname". - File lib64 = new File(Environment.getRootDirectory(), LIB64_DIR_NAME); + String apkRoot = calculateApkRoot(pkgSetting.codePath); + File lib64 = new File(apkRoot, LIB64_DIR_NAME); File packLib64 = new File(lib64, apkName); - libDir = (packLib64.exists()) - ? lib64 - : new File(Environment.getRootDirectory(), LIB_DIR_NAME); + libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME); } else { libDir = mAppLibInstallDir; } diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index d2eccbe..ebe1bed 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -42,6 +42,15 @@ typedef enum Command { } Command; /* + * Pseudolocalization methods + */ +typedef enum PseudolocalizationMethod { + NO_PSEUDOLOCALIZATION = 0, + PSEUDO_ACCENTED, + PSEUDO_BIDI, +} PseudolocalizationMethod; + +/* * Bundle of goodies, including everything specified on the command line. */ class Bundle { @@ -50,7 +59,7 @@ public: : mCmd(kCommandUnknown), mVerbose(false), mAndroidList(false), mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false), mUpdate(false), mExtending(false), - mRequireLocalization(false), mPseudolocalize(false), + mRequireLocalization(false), mPseudolocalize(NO_PSEUDOLOCALIZATION), mWantUTF16(false), mValues(false), mIncludeMetaData(false), mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL), mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL), @@ -95,8 +104,8 @@ public: void setExtending(bool val) { mExtending = val; } bool getRequireLocalization(void) const { return mRequireLocalization; } void setRequireLocalization(bool val) { mRequireLocalization = val; } - bool getPseudolocalize(void) const { return mPseudolocalize; } - void setPseudolocalize(bool val) { mPseudolocalize = val; } + short getPseudolocalize(void) const { return mPseudolocalize; } + void setPseudolocalize(short val) { mPseudolocalize = val; } void setWantUTF16(bool val) { mWantUTF16 = val; } bool getValues(void) const { return mValues; } void setValues(bool val) { mValues = val; } @@ -259,7 +268,7 @@ private: bool mUpdate; bool mExtending; bool mRequireLocalization; - bool mPseudolocalize; + short mPseudolocalize; bool mWantUTF16; bool mValues; bool mIncludeMetaData; diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 44b8340..0af1ce1 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -2048,14 +2048,17 @@ int doPackage(Bundle* bundle) FILE* fp; String8 dependencyFile; - // -c zz_ZZ means do pseudolocalization + // -c en_XA or/and ar_XB means do pseudolocalization ResourceFilter filter; err = filter.parse(bundle->getConfigurations()); if (err != NO_ERROR) { goto bail; } if (filter.containsPseudo()) { - bundle->setPseudolocalize(true); + bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED); + } + if (filter.containsPseudoBidi()) { + bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI); } N = bundle->getFileSpecCount(); diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp index e8a2be4..8ca852e 100644 --- a/tools/aapt/ResourceFilter.cpp +++ b/tools/aapt/ResourceFilter.cpp @@ -24,8 +24,10 @@ ResourceFilter::parse(const char* arg) String8 part(p, q-p); - if (part == "zz_ZZ") { - mContainsPseudo = true; + if (part == "en_XA") { + mContainsPseudoAccented = true; + } else if (part == "ar_XB") { + mContainsPseudoBidi = true; } int axis; AxisValue value; diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h index 0d127ba..c57770e 100644 --- a/tools/aapt/ResourceFilter.h +++ b/tools/aapt/ResourceFilter.h @@ -16,19 +16,22 @@ class ResourceFilter { public: - ResourceFilter() : mData(), mContainsPseudo(false) {} + ResourceFilter() : mData(), mContainsPseudoAccented(false), + mContainsPseudoBidi(false) {} status_t parse(const char* arg); bool isEmpty() const; bool match(int axis, const ResTable_config& config) const; bool match(const ResTable_config& config) const; const SortedVector<AxisValue>* configsForAxis(int axis) const; - inline bool containsPseudo() const { return mContainsPseudo; } + inline bool containsPseudo() const { return mContainsPseudoAccented; } + inline bool containsPseudoBidi() const { return mContainsPseudoBidi; } private: bool match(int axis, const AxisValue& value) const; KeyedVector<int,SortedVector<AxisValue> > mData; - bool mContainsPseudo; + bool mContainsPseudoAccented; + bool mContainsPseudoBidi; }; #endif diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 0fb2606..25bb26e 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -25,7 +25,7 @@ status_t compileXmlFile(const sp<AaptAssets>& assets, if (root == NULL) { return UNKNOWN_ERROR; } - + return compileXmlFile(assets, root, target, table, options); } @@ -577,13 +577,13 @@ status_t parseAndAddBag(Bundle* bundle, int32_t curFormat, bool isFormatted, const String16& product, - bool pseudolocalize, + PseudolocalizationMethod pseudolocalize, const bool overwrite, ResourceTable* outTable) { status_t err; const String16 item16("item"); - + String16 str; Vector<StringPool::entry_style_span> spans; err = parseStyledString(bundle, in->getPrintableSource().string(), @@ -672,7 +672,7 @@ status_t parseAndAddEntry(Bundle* bundle, int32_t curFormat, bool isFormatted, const String16& product, - bool pseudolocalize, + PseudolocalizationMethod pseudolocalize, const bool overwrite, KeyedVector<type_ident_pair_t, bool>* skippedResourceNames, ResourceTable* outTable) @@ -854,10 +854,16 @@ status_t compileResourceFile(Bundle* bundle, ResTable_config curParams(defParams); ResTable_config pseudoParams(curParams); - pseudoParams.language[0] = 'z'; - pseudoParams.language[1] = 'z'; - pseudoParams.country[0] = 'Z'; - pseudoParams.country[1] = 'Z'; + pseudoParams.language[0] = 'e'; + pseudoParams.language[1] = 'n'; + pseudoParams.country[0] = 'X'; + pseudoParams.country[1] = 'A'; + + ResTable_config pseudoBidiParams(curParams); + pseudoBidiParams.language[0] = 'a'; + pseudoBidiParams.language[1] = 'r'; + pseudoBidiParams.country[0] = 'X'; + pseudoBidiParams.country[1] = 'B'; while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { if (code == ResXMLTree::START_TAG) { @@ -1334,6 +1340,7 @@ status_t compileResourceFile(Bundle* bundle, name, locale, SourcePos(in->getPrintableSource(), block.getLineNumber())); + curIsPseudolocalizable = fileIsTranslatable; } if (formatted == false16) { @@ -1389,6 +1396,7 @@ status_t compileResourceFile(Bundle* bundle, curTag = &plurals16; curType = plurals16; curIsBag = true; + curIsPseudolocalizable = fileIsTranslatable; } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) { curTag = &array16; curType = array16; @@ -1410,25 +1418,23 @@ status_t compileResourceFile(Bundle* bundle, } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) { // Check whether these strings need valid formats. // (simplified form of what string16 does above) + bool isTranslatable = false; size_t n = block.getAttributeCount(); // Pseudolocalizable by default, unless this string array isn't // translatable. - curIsPseudolocalizable = true; for (size_t i = 0; i < n; i++) { size_t length; const uint16_t* attr = block.getAttributeName(i, &length); - if (strcmp16(attr, translatable16.string()) == 0) { + if (strcmp16(attr, formatted16.string()) == 0) { const uint16_t* value = block.getAttributeStringValue(i, &length); if (strcmp16(value, false16.string()) == 0) { - curIsPseudolocalizable = false; + curIsFormatted = false; } - } - - if (strcmp16(attr, formatted16.string()) == 0) { + } else if (strcmp16(attr, translatable16.string()) == 0) { const uint16_t* value = block.getAttributeStringValue(i, &length); if (strcmp16(value, false16.string()) == 0) { - curIsFormatted = false; + isTranslatable = false; } } } @@ -1438,6 +1444,7 @@ status_t compileResourceFile(Bundle* bundle, curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING; curIsBag = true; curIsBagReplaceOnOverwrite = true; + curIsPseudolocalizable = isTranslatable && fileIsTranslatable; } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) { curTag = &integer_array16; curType = array16; @@ -1559,19 +1566,29 @@ status_t compileResourceFile(Bundle* bundle, err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType, ident, parentIdent, itemIdent, curFormat, curIsFormatted, - product, false, overwrite, outTable); + product, NO_PSEUDOLOCALIZATION, overwrite, outTable); if (err == NO_ERROR) { if (curIsPseudolocalizable && localeIsDefined(curParams) - && bundle->getPseudolocalize()) { + && bundle->getPseudolocalize() > 0) { // pseudolocalize here -#if 1 - block.setPosition(parserPosition); - err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage, - curType, ident, parentIdent, itemIdent, curFormat, - curIsFormatted, product, true, overwrite, outTable); -#endif + if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) == + PSEUDO_ACCENTED) { + block.setPosition(parserPosition); + err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage, + curType, ident, parentIdent, itemIdent, curFormat, + curIsFormatted, product, PSEUDO_ACCENTED, + overwrite, outTable); + } + if ((PSEUDO_BIDI & bundle->getPseudolocalize()) == + PSEUDO_BIDI) { + block.setPosition(parserPosition); + err = parseAndAddBag(bundle, in, &block, pseudoBidiParams, myPackage, + curType, ident, parentIdent, itemIdent, curFormat, + curIsFormatted, product, PSEUDO_BIDI, + overwrite, outTable); + } } - } + } if (err != NO_ERROR) { hasErrors = localHasErrors = true; } @@ -1592,20 +1609,31 @@ status_t compileResourceFile(Bundle* bundle, err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident, *curTag, curIsStyled, curFormat, curIsFormatted, - product, false, overwrite, &skippedResourceNames, outTable); + product, NO_PSEUDOLOCALIZATION, overwrite, &skippedResourceNames, outTable); if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR? hasErrors = localHasErrors = true; } else if (err == NO_ERROR) { if (curIsPseudolocalizable && localeIsDefined(curParams) - && bundle->getPseudolocalize()) { + && bundle->getPseudolocalize() > 0) { // pseudolocalize here - block.setPosition(parserPosition); - err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType, - ident, *curTag, curIsStyled, curFormat, - curIsFormatted, product, - true, overwrite, &skippedResourceNames, outTable); + if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) == + PSEUDO_ACCENTED) { + block.setPosition(parserPosition); + err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType, + ident, *curTag, curIsStyled, curFormat, + curIsFormatted, product, + PSEUDO_ACCENTED, overwrite, &skippedResourceNames, outTable); + } + if ((PSEUDO_BIDI & bundle->getPseudolocalize()) == + PSEUDO_BIDI) { + block.setPosition(parserPosition); + err = parseAndAddEntry(bundle, in, &block, pseudoBidiParams, + myPackage, curType, ident, *curTag, curIsStyled, curFormat, + curIsFormatted, product, + PSEUDO_BIDI, overwrite, &skippedResourceNames, outTable); + } if (err != NO_ERROR) { hasErrors = localHasErrors = true; } @@ -2637,8 +2665,8 @@ ResourceTable::validateLocalizations(void) continue; } - // don't bother with the pseudolocale "zz_ZZ" - if (config != "zz_ZZ") { + // don't bother with the pseudolocale "en_XA" or "ar_XB" + if (config != "en_XA" && config != "ar_XB") { if (configSrcMap.find(config) == configSrcMap.end()) { // okay, no specific localization found. it's possible that we are // requiring a specific regional localization [e.g. de_DE] but there is an diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp index a663ad5..607d419 100644 --- a/tools/aapt/XMLNode.cpp +++ b/tools/aapt/XMLNode.cpp @@ -187,7 +187,7 @@ status_t parseStyledString(Bundle* bundle, String16* outString, Vector<StringPool::entry_style_span>* outSpans, bool isFormatted, - bool pseudolocalize) + PseudolocalizationMethod pseudolocalize) { Vector<StringPool::entry_style_span> spanStack; String16 curString; @@ -198,21 +198,30 @@ status_t parseStyledString(Bundle* bundle, size_t len; ResXMLTree::event_code_t code; + // Bracketing if pseudolocalization accented method specified. + if (pseudolocalize == PSEUDO_ACCENTED) { + curString.append(String16(String8("["))); + } while ((code=inXml->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { - if (code == ResXMLTree::TEXT) { String16 text(inXml->getText(&len)); if (firstTime && text.size() > 0) { firstTime = false; if (text.string()[0] == '@') { // If this is a resource reference, don't do the pseudoloc. - pseudolocalize = false; + pseudolocalize = NO_PSEUDOLOCALIZATION; } } - if (xliffDepth == 0 && pseudolocalize) { - std::string orig(String8(text).string()); - std::string pseudo = pseudolocalize_string(orig); - curString.append(String16(String8(pseudo.c_str()))); + if (xliffDepth == 0 && pseudolocalize > 0) { + String16 pseudo; + if (pseudolocalize == PSEUDO_ACCENTED) { + pseudo = pseudolocalize_string(text); + } else if (pseudolocalize == PSEUDO_BIDI) { + pseudo = pseudobidi_string(text); + } else { + pseudo = text; + } + curString.append(pseudo); } else { if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) { return UNKNOWN_ERROR; @@ -352,6 +361,25 @@ moveon: } } + // Bracketing if pseudolocalization accented method specified. + if (pseudolocalize == PSEUDO_ACCENTED) { + const char16_t* str = outString->string(); + const char16_t* p = str; + const char16_t* e = p + outString->size(); + int words_cnt = 0; + while (p < e) { + if (isspace(*p)) { + words_cnt++; + } + p++; + } + unsigned int length = words_cnt > 3 ? outString->size() : + outString->size() / 2; + curString.append(String16(String8(" "))); + curString.append(pseudo_generate_expansion(length)); + curString.append(String16(String8("]"))); + } + if (code == ResXMLTree::BAD_DOCUMENT) { SourcePos(String8(fileName), inXml->getLineNumber()).error( "Error parsing XML\n"); diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h index 05624b7..ccbf9f4 100644 --- a/tools/aapt/XMLNode.h +++ b/tools/aapt/XMLNode.h @@ -26,7 +26,7 @@ status_t parseStyledString(Bundle* bundle, String16* outString, Vector<StringPool::entry_style_span>* outSpans, bool isFormatted, - bool isPseudolocalizable); + PseudolocalizationMethod isPseudolocalizable); void printXMLBlock(ResXMLTree* block); diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp index 9e50c5a..60aa2b2 100644 --- a/tools/aapt/pseudolocalize.cpp +++ b/tools/aapt/pseudolocalize.cpp @@ -2,89 +2,155 @@ using namespace std; +// String basis to generate expansion +static const String16 k_expansion_string = String16("one two three " + "four five six seven eight nine ten eleven twelve thirteen " + "fourteen fiveteen sixteen seventeen nineteen twenty"); + +// Special unicode characters to override directionality of the words +static const String16 k_rlm = String16("\xe2\x80\x8f"); +static const String16 k_rlo = String16("\xE2\x80\xae"); +static const String16 k_pdf = String16("\xE2\x80\xac"); + +// Placeholder marks +static const String16 k_placeholder_open = String16("\xc2\xbb"); +static const String16 k_placeholder_close = String16("\xc2\xab"); + static const char* -pseudolocalize_char(char c) +pseudolocalize_char(const char16_t 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 'a': return "\xc3\xa5"; + case 'b': return "\xc9\x93"; + case 'c': return "\xc3\xa7"; + case 'd': return "\xc3\xb0"; + case 'e': return "\xc3\xa9"; case 'f': return "\xc6\x92"; case 'g': return "\xc4\x9d"; - case 'h': return "\xd1\x9b"; - case 'i': return "\xcf\x8a"; + case 'h': return "\xc4\xa5"; + case 'i': return "\xc3\xae"; case 'j': return "\xc4\xb5"; - case 'k': return "\xc4\xb8"; - case 'l': return "\xc4\xba"; + case 'k': return "\xc4\xb7"; + case 'l': return "\xc4\xbc"; case 'm': return "\xe1\xb8\xbf"; - case 'n': return "\xd0\xb8"; - case 'o': return "\xcf\x8c"; - case 'p': return "\xcf\x81"; + case 'n': return "\xc3\xb1"; + case 'o': return "\xc3\xb6"; + case 'p': return "\xc3\xbe"; case 'q': return "\x51"; - case 'r': return "\xd2\x91"; + case 'r': return "\xc5\x95"; case 's': return "\xc5\xa1"; - case 't': return "\xd1\x82"; - case 'u': return "\xce\xb0"; + case 't': return "\xc5\xa3"; + case 'u': return "\xc3\xbb"; case 'v': return "\x56"; - case 'w': return "\xe1\xba\x85"; + case 'w': return "\xc5\xb5"; case 'x': return "\xd1\x85"; - case 'y': return "\xe1\xbb\xb3"; - case 'z': return "\xc5\xba"; + case 'y': return "\xc3\xbd"; + case 'z': return "\xc5\xbe"; 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 'C': return "\xc3\x87"; + case 'D': return "\xc3\x90"; + case 'E': return "\xc3\x89"; + case 'G': return "\xc4\x9c"; + case 'H': return "\xc4\xa4"; + case 'I': return "\xc3\x8e"; + case 'J': return "\xc4\xb4"; case 'K': return "\xc4\xb6"; - case 'L': return "\xc5\x81"; + case 'L': return "\xc4\xbb"; case 'M': return "\xe1\xb8\xbe"; - case 'N': return "\xc5\x83"; - case 'O': return "\xce\x98"; - case 'P': return "\xcf\x81"; + case 'N': return "\xc3\x91"; + case 'O': return "\xc3\x96"; + case 'P': return "\xc3\x9e"; 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 'R': return "\xc5\x94"; + case 'S': return "\xc5\xa0"; + case 'T': return "\xc5\xa2"; + case 'U': return "\xc3\x9b"; case 'V': return "\xce\xbd"; - case 'W': return "\xe1\xba\x84"; + case 'W': return "\xc5\xb4"; case 'X': return "\xc3\x97"; - case 'Y': return "\xc2\xa5"; + case 'Y': return "\xc3\x9d"; case 'Z': return "\xc5\xbd"; + case '!': return "\xc2\xa1"; + case '?': return "\xc2\xbf"; + case '$': return "\xe2\x82\xac"; default: return NULL; } } +static bool +is_possible_normal_placeholder_end(const char16_t c) { + switch (c) { + case 's': return true; + case 'S': return true; + case 'c': return true; + case 'C': return true; + case 'd': return true; + case 'o': return true; + case 'x': return true; + case 'X': return true; + case 'f': return true; + case 'e': return true; + case 'E': return true; + case 'g': return true; + case 'G': return true; + case 'a': return true; + case 'A': return true; + case 'b': return true; + case 'B': return true; + case 'h': return true; + case 'H': return true; + case '%': return true; + case 'n': return true; + default: return false; + } +} + +String16 +pseudo_generate_expansion(const unsigned int length) { + String16 result = k_expansion_string; + const char16_t* s = result.string(); + if (result.size() < length) { + result += String16(" "); + result += pseudo_generate_expansion(length - result.size()); + } else { + int ext = 0; + // Should contain only whole words, so looking for a space + for (unsigned int i = length + 1; i < result.size(); ++i) { + ++ext; + if (s[i] == ' ') { + break; + } + } + result.remove(length + ext, 0); + } + return result; +} + /** * 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) +String16 +pseudolocalize_string(const String16& source) { - const char* s = source.c_str(); - string result; - const size_t I = source.length(); + const char16_t* s = source.string(); + String16 result; + const size_t I = source.size(); for (size_t i=0; i<I; i++) { - char c = s[i]; + char16_t c = s[i]; if (c == '\\') { + // Escape syntax, no need to pseudolocalize if (i<I-1) { - result += '\\'; + result += String16("\\"); i++; c = s[i]; switch (c) { case 'u': // this one takes up 5 chars - result += string(s+i, 5); + result += String16(s+i, 5); i += 4; break; case 't': @@ -96,24 +162,107 @@ pseudolocalize_string(const string& source) case '\'': case '\\': default: - result += c; + result.append(&c, 1); break; } } else { - result += c; + result.append(&c, 1); + } + } else if (c == '%') { + // Placeholder syntax, no need to pseudolocalize + result += k_placeholder_open; + bool end = false; + result.append(&c, 1); + while (!end && i < I) { + ++i; + c = s[i]; + result.append(&c, 1); + if (is_possible_normal_placeholder_end(c)) { + end = true; + } else if (c == 't') { + ++i; + c = s[i]; + result.append(&c, 1); + end = true; + } + } + result += k_placeholder_close; + } else if (c == '<' || c == '&') { + // html syntax, no need to pseudolocalize + bool tag_closed = false; + while (!tag_closed && i < I) { + if (c == '&') { + String16 escape_text; + escape_text.append(&c, 1); + bool end = false; + size_t htmlCodePos = i; + while (!end && htmlCodePos < I) { + ++htmlCodePos; + c = s[htmlCodePos]; + escape_text.append(&c, 1); + // Valid html code + if (c == ';') { + end = true; + i = htmlCodePos; + } + // Wrong html code + else if (!((c == '#' || + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9')))) { + end = true; + } + } + result += escape_text; + if (escape_text != String16("<")) { + tag_closed = true; + } + continue; + } + if (c == '>') { + tag_closed = true; + result.append(&c, 1); + continue; + } + result.append(&c, 1); + i++; + c = s[i]; } } else { + // This is a pure text that should be pseudolocalized const char* p = pseudolocalize_char(c); if (p != NULL) { - result += p; + result += String16(p); } else { - result += c; + result.append(&c, 1); } } } - - //printf("result=\'%s\'\n", result.c_str()); return result; } +String16 +pseudobidi_string(const String16& source) +{ + const char16_t* s = source.string(); + String16 result; + result += k_rlm; + result += k_rlo; + for (size_t i=0; i<source.size(); i++) { + char16_t c = s[i]; + switch(c) { + case ' ': result += k_pdf; + result += k_rlm; + result.append(&c, 1); + result += k_rlm; + result += k_rlo; + break; + default: result.append(&c, 1); + break; + } + } + result += k_pdf; + result += k_rlm; + return result; +} diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h index 94cb034..e6ab18e 100644 --- a/tools/aapt/pseudolocalize.h +++ b/tools/aapt/pseudolocalize.h @@ -1,9 +1,18 @@ #ifndef HOST_PSEUDOLOCALIZE_H #define HOST_PSEUDOLOCALIZE_H +#include "StringPool.h" + #include <string> -std::string pseudolocalize_string(const std::string& source); +String16 pseudolocalize_string(const String16& source); +// Surrounds every word in the sentance with specific characters that makes +// the word directionality RTL. +String16 pseudobidi_string(const String16& source); +// Generates expansion string based on the specified lenght. +// Generated string could not be shorter that length, but it could be slightly +// longer. +String16 pseudo_generate_expansion(const unsigned int length); #endif // HOST_PSEUDOLOCALIZE_H diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index de2e592..25eaaf5 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -428,6 +428,16 @@ public class Paint_Delegate { } @LayoutlibDelegate + /*package*/ static boolean isElegantTextHeight(Paint thisPaint) { + return false; + } + + @LayoutlibDelegate + /*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) { + // TODO + } + + @LayoutlibDelegate /*package*/ static float getTextSize(Paint thisPaint) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); 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 6595ce1..08e9d99 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 @@ -58,6 +58,7 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; +import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -101,6 +102,7 @@ public final class BridgeContext extends Context { private final ApplicationInfo mApplicationInfo; private final IProjectCallback mProjectCallback; private final WindowManager mWindowManager; + private final DisplayManager mDisplayManager; private Resources.Theme mTheme; @@ -149,6 +151,7 @@ public final class BridgeContext extends Context { } mWindowManager = new WindowManagerImpl(mMetrics); + mDisplayManager = new DisplayManager(this); } /** @@ -455,6 +458,10 @@ public final class BridgeContext extends Context { return new PowerManager(this, new BridgePowerManager(), new Handler()); } + if (DISPLAY_SERVICE.equals(service)) { + return mDisplayManager; + } + throw new UnsupportedOperationException("Unsupported Service: " + service); } |