diff options
351 files changed, 12398 insertions, 6688 deletions
@@ -132,6 +132,8 @@ LOCAL_SRC_FILES += \ core/java/android/os/IRemoteCallback.aidl \ core/java/android/os/IUpdateLock.aidl \ core/java/android/os/IVibratorService.aidl \ + core/java/android/service/dreams/IDreamManager.aidl \ + core/java/android/service/dreams/IDreamService.aidl \ core/java/android/service/wallpaper/IWallpaperConnection.aidl \ core/java/android/service/wallpaper/IWallpaperEngine.aidl \ core/java/android/service/wallpaper/IWallpaperService.aidl \ @@ -25204,7 +25204,6 @@ package android.webkit { method public java.lang.String getTitle(); method public java.lang.String getUrl(); method public deprecated int getVisibleTitleHeight(); - method public deprecated android.view.View getZoomControls(); method public void goBack(); method public void goBackOrForward(int); method public void goForward(); @@ -41832,7 +41831,7 @@ package junit.framework { method public static void fail(); } - public class AssertionFailedError extends java.lang.Error { + public class AssertionFailedError extends java.lang.AssertionError { ctor public AssertionFailedError(); ctor public AssertionFailedError(java.lang.String); } @@ -41890,9 +41889,9 @@ package junit.framework { method public synchronized void addListener(junit.framework.TestListener); method public void endTest(junit.framework.Test); method public synchronized int errorCount(); - method public synchronized java.util.Enumeration errors(); + method public synchronized java.util.Enumeration<junit.framework.TestFailure> errors(); method public synchronized int failureCount(); - method public synchronized java.util.Enumeration failures(); + method public synchronized java.util.Enumeration<junit.framework.TestFailure> failures(); method public synchronized void removeListener(junit.framework.TestListener); method protected void run(junit.framework.TestCase); method public synchronized int runCount(); @@ -41909,21 +41908,21 @@ package junit.framework { public class TestSuite implements junit.framework.Test { ctor public TestSuite(); - ctor public TestSuite(java.lang.Class, java.lang.String); - ctor public TestSuite(java.lang.Class); + ctor public TestSuite(java.lang.Class<?>); + ctor public TestSuite(java.lang.Class<? extends junit.framework.TestCase>, java.lang.String); ctor public TestSuite(java.lang.String); method public void addTest(junit.framework.Test); - method public void addTestSuite(java.lang.Class); + method public void addTestSuite(java.lang.Class<? extends junit.framework.TestCase>); method public int countTestCases(); - method public static junit.framework.Test createTest(java.lang.Class, java.lang.String); + method public static junit.framework.Test createTest(java.lang.Class<?>, java.lang.String); method public java.lang.String getName(); - method public static java.lang.reflect.Constructor getTestConstructor(java.lang.Class) throws java.lang.NoSuchMethodException; + method public static java.lang.reflect.Constructor<?> getTestConstructor(java.lang.Class) throws java.lang.NoSuchMethodException; method public void run(junit.framework.TestResult); method public void runTest(junit.framework.Test, junit.framework.TestResult); method public void setName(java.lang.String); method public junit.framework.Test testAt(int); method public int testCount(); - method public java.util.Enumeration tests(); + method public java.util.Enumeration<junit.framework.Test> tests(); } } @@ -41946,7 +41945,7 @@ package junit.runner { method protected static java.util.Properties getPreferences(); method public junit.framework.Test getTest(java.lang.String); method public static boolean inVAJava(); - method protected java.lang.Class loadSuiteClass(java.lang.String) throws java.lang.ClassNotFoundException; + method protected java.lang.Class<?> loadSuiteClass(java.lang.String) throws java.lang.ClassNotFoundException; method protected java.lang.String processArguments(java.lang.String[]); method protected abstract void runFailed(java.lang.String); method public static void savePreferences() throws java.io.IOException; diff --git a/api/current.txt b/api/current.txt index 3e177ad..b2a8b2d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -102,6 +102,7 @@ package android { field public static final java.lang.String SET_ALWAYS_FINISH = "android.permission.SET_ALWAYS_FINISH"; field public static final java.lang.String SET_ANIMATION_SCALE = "android.permission.SET_ANIMATION_SCALE"; field public static final java.lang.String SET_DEBUG_APP = "android.permission.SET_DEBUG_APP"; + field public static final java.lang.String SET_KEYBOARD_LAYOUT = "android.permission.SET_KEYBOARD_LAYOUT"; field public static final java.lang.String SET_ORIENTATION = "android.permission.SET_ORIENTATION"; field public static final java.lang.String SET_POINTER_SPEED = "android.permission.SET_POINTER_SPEED"; field public static final deprecated java.lang.String SET_PREFERRED_APPLICATIONS = "android.permission.SET_PREFERRED_APPLICATIONS"; @@ -2881,14 +2882,10 @@ package android.app { public class ActivityOptions { method public void join(android.app.ActivityOptions); method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int); - method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int, android.app.ActivityOptions.OnAnimationStartedListener); + method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int); method public android.os.Bundle toBundle(); } - public static abstract interface ActivityOptions.OnAnimationStartedListener { - method public abstract void onAnimationStarted(); - } - public class AlarmManager { method public void cancel(android.app.PendingIntent); method public void set(int, long, android.app.PendingIntent); @@ -8495,6 +8492,7 @@ package android.graphics { method public android.graphics.Paint.Align getTextAlign(); method public void getTextBounds(java.lang.String, int, int, android.graphics.Rect); method public void getTextBounds(char[], int, int, android.graphics.Rect); + method public java.util.Locale getTextLocale(); method public void getTextPath(char[], int, int, float, float, android.graphics.Path); method public void getTextPath(java.lang.String, int, int, float, float, android.graphics.Path); method public float getTextScaleX(); @@ -8544,6 +8542,7 @@ package android.graphics { method public void setStyle(android.graphics.Paint.Style); method public void setSubpixelText(boolean); method public void setTextAlign(android.graphics.Paint.Align); + method public void setTextLocale(java.util.Locale); method public void setTextScaleX(float); method public void setTextSize(float); method public void setTextSkewX(float); @@ -17996,15 +17995,24 @@ package android.renderscript { method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type, int); method public static android.renderscript.Allocation createTyped(android.renderscript.RenderScript, android.renderscript.Type); method public void generateMipmaps(); + method public int getBytesSize(); + method public android.renderscript.Element getElement(); + method public android.view.Surface getSurface(); method public android.renderscript.Type getType(); + method public int getUsage(); + method public void ioReceive(); + method public void ioSend(); method public synchronized void resize(int); method public void setFromFieldPacker(int, android.renderscript.FieldPacker); method public void setFromFieldPacker(int, int, android.renderscript.FieldPacker); + method public void setSurface(android.view.Surface); method public void syncAll(int); field public static final int USAGE_GRAPHICS_CONSTANTS = 8; // 0x8 field public static final int USAGE_GRAPHICS_RENDER_TARGET = 16; // 0x10 field public static final int USAGE_GRAPHICS_TEXTURE = 2; // 0x2 field public static final int USAGE_GRAPHICS_VERTEX = 4; // 0x4 + field public static final int USAGE_IO_INPUT = 32; // 0x20 + field public static final int USAGE_IO_OUTPUT = 64; // 0x40 field public static final int USAGE_SCRIPT = 1; // 0x1 } @@ -18092,6 +18100,7 @@ package android.renderscript { method public static android.renderscript.Element F64_2(android.renderscript.RenderScript); method public static android.renderscript.Element F64_3(android.renderscript.RenderScript); method public static android.renderscript.Element F64_4(android.renderscript.RenderScript); + method public static android.renderscript.Element FONT(android.renderscript.RenderScript); method public static android.renderscript.Element I16(android.renderscript.RenderScript); method public static android.renderscript.Element I16_2(android.renderscript.RenderScript); method public static android.renderscript.Element I16_3(android.renderscript.RenderScript); @@ -18143,6 +18152,15 @@ package android.renderscript { method public static android.renderscript.Element U8_4(android.renderscript.RenderScript); method public static android.renderscript.Element createPixel(android.renderscript.RenderScript, android.renderscript.Element.DataType, android.renderscript.Element.DataKind); method public static android.renderscript.Element createVector(android.renderscript.RenderScript, android.renderscript.Element.DataType, int); + method public int getBytesSize(); + method public android.renderscript.Element.DataKind getDataKind(); + method public android.renderscript.Element.DataType getDataType(); + method public android.renderscript.Element getSubElement(int); + method public int getSubElementArraySize(int); + method public int getSubElementCount(); + method public java.lang.String getSubElementName(int); + method public int getSubElementOffsetBytes(int); + method public int getVectorSize(); method public boolean isCompatible(android.renderscript.Element); method public boolean isComplex(); } @@ -18175,8 +18193,10 @@ package android.renderscript { enum_constant public static final android.renderscript.Element.DataType MATRIX_2X2; enum_constant public static final android.renderscript.Element.DataType MATRIX_3X3; enum_constant public static final android.renderscript.Element.DataType MATRIX_4X4; + enum_constant public static final android.renderscript.Element.DataType NONE; enum_constant public static final android.renderscript.Element.DataType RS_ALLOCATION; enum_constant public static final android.renderscript.Element.DataType RS_ELEMENT; + enum_constant public static final android.renderscript.Element.DataType RS_FONT; enum_constant public static final android.renderscript.Element.DataType RS_MESH; enum_constant public static final android.renderscript.Element.DataType RS_PROGRAM_FRAGMENT; enum_constant public static final android.renderscript.Element.DataType RS_PROGRAM_RASTER; @@ -18489,12 +18509,18 @@ package android.renderscript { method public void bindConstants(android.renderscript.Allocation, int); method public void bindSampler(android.renderscript.Sampler, int) throws java.lang.IllegalArgumentException; method public void bindTexture(android.renderscript.Allocation, int) throws java.lang.IllegalArgumentException; + method public android.renderscript.Type getConstant(int); + method public int getConstantCount(); + method public int getTextureCount(); + method public java.lang.String getTextureName(int); + method public android.renderscript.Program.TextureType getTextureType(int); } public static class Program.BaseProgramBuilder { ctor protected Program.BaseProgramBuilder(android.renderscript.RenderScript); method public android.renderscript.Program.BaseProgramBuilder addConstant(android.renderscript.Type) throws java.lang.IllegalStateException; method public android.renderscript.Program.BaseProgramBuilder addTexture(android.renderscript.Program.TextureType) throws java.lang.IllegalArgumentException; + method public android.renderscript.Program.BaseProgramBuilder addTexture(android.renderscript.Program.TextureType, java.lang.String) throws java.lang.IllegalArgumentException; method public int getCurrentConstantIndex(); method public int getCurrentTextureIndex(); method protected void initProgram(android.renderscript.Program); @@ -18550,6 +18576,8 @@ package android.renderscript { method public static android.renderscript.ProgramRaster CULL_BACK(android.renderscript.RenderScript); method public static android.renderscript.ProgramRaster CULL_FRONT(android.renderscript.RenderScript); method public static android.renderscript.ProgramRaster CULL_NONE(android.renderscript.RenderScript); + method public android.renderscript.ProgramRaster.CullMode getCullMode(); + method public boolean isPointSpriteEnabled(); } public static class ProgramRaster.Builder { @@ -18572,6 +18600,15 @@ package android.renderscript { method public static android.renderscript.ProgramStore BLEND_ALPHA_DEPTH_TEST(android.renderscript.RenderScript); method public static android.renderscript.ProgramStore BLEND_NONE_DEPTH_NONE(android.renderscript.RenderScript); method public static android.renderscript.ProgramStore BLEND_NONE_DEPTH_TEST(android.renderscript.RenderScript); + method public android.renderscript.ProgramStore.BlendDstFunc getBlendDstFunc(); + method public android.renderscript.ProgramStore.BlendSrcFunc getBlendSrcFunc(); + method public android.renderscript.ProgramStore.DepthFunc getDepthFunc(); + method public boolean isColorMaskAlphaEnabled(); + method public boolean isColorMaskBlueEnabled(); + method public boolean isColorMaskGreenEnabled(); + method public boolean isColorMaskRedEnabled(); + method public boolean isDepthMaskEnabled(); + method public boolean isDitherEnabled(); } public static final class ProgramStore.BlendDstFunc extends java.lang.Enum { @@ -18624,6 +18661,8 @@ package android.renderscript { } public class ProgramVertex extends android.renderscript.Program { + method public android.renderscript.Element getInput(int); + method public int getInputCount(); } public static class ProgramVertex.Builder extends android.renderscript.Program.BaseProgramBuilder { @@ -18761,6 +18800,11 @@ package android.renderscript { method public static android.renderscript.Sampler WRAP_LINEAR(android.renderscript.RenderScript); method public static android.renderscript.Sampler WRAP_LINEAR_MIP_LINEAR(android.renderscript.RenderScript); method public static android.renderscript.Sampler WRAP_NEAREST(android.renderscript.RenderScript); + method public float getAnisotropy(); + method public android.renderscript.Sampler.Value getMagnification(); + method public android.renderscript.Sampler.Value getMinification(); + method public android.renderscript.Sampler.Value getWrapS(); + method public android.renderscript.Sampler.Value getWrapT(); } public static class Sampler.Builder { @@ -19700,12 +19744,12 @@ package android.test { method public final void testApplicationTestCaseSetUpProperly() throws java.lang.Exception; } - public class AssertionFailedError extends java.lang.Error { + public deprecated class AssertionFailedError extends java.lang.Error { ctor public AssertionFailedError(); ctor public AssertionFailedError(java.lang.String); } - public class ComparisonFailure extends android.test.AssertionFailedError { + public deprecated class ComparisonFailure extends android.test.AssertionFailedError { ctor public ComparisonFailure(java.lang.String, java.lang.String, java.lang.String); } @@ -19747,6 +19791,7 @@ package android.test { ctor public InstrumentationTestSuite(android.app.Instrumentation); ctor public InstrumentationTestSuite(java.lang.String, android.app.Instrumentation); ctor public InstrumentationTestSuite(java.lang.Class, android.app.Instrumentation); + method public void addTestSuite(java.lang.Class); } public class IsolatedContext extends android.content.ContextWrapper { @@ -22272,6 +22317,7 @@ package android.view { method public java.util.List<android.view.InputDevice.MotionRange> getMotionRanges(); method public java.lang.String getName(); method public int getSources(); + method public boolean isVirtual(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int KEYBOARD_TYPE_ALPHABETIC = 2; // 0x2 @@ -22331,7 +22377,8 @@ package android.view { method public abstract void onInputQueueDestroyed(android.view.InputQueue); } - public class KeyCharacterMap { + public class KeyCharacterMap implements android.os.Parcelable { + method public int describeContents(); method public static boolean deviceHasKey(int); method public static boolean[] deviceHasKeys(int[]); method public int get(int, int); @@ -22346,10 +22393,12 @@ package android.view { method public char getNumber(int); method public boolean isPrintingKey(int); method public static android.view.KeyCharacterMap load(int); + method public void writeToParcel(android.os.Parcel, int); field public static final int ALPHA = 3; // 0x3 field public static final deprecated int BUILT_IN_KEYBOARD = 0; // 0x0 field public static final int COMBINING_ACCENT = -2147483648; // 0x80000000 field public static final int COMBINING_ACCENT_MASK = 2147483647; // 0x7fffffff + field public static final android.os.Parcelable.Creator CREATOR; field public static final int FULL = 4; // 0x4 field public static final char HEX_INPUT = 61184; // 0xef00 '\uef00' field public static final int MODIFIER_BEHAVIOR_CHORDED = 0; // 0x0 @@ -23533,6 +23582,10 @@ package android.view { method public void postInvalidate(int, int, int, int); method public void postInvalidateDelayed(long); method public void postInvalidateDelayed(long, int, int, int, int); + method public void postInvalidateOnAnimation(); + method public void postInvalidateOnAnimation(int, int, int, int); + method public void postOnAnimation(java.lang.Runnable); + method public void postOnAnimationDelayed(java.lang.Runnable, long); method public void refreshDrawableState(); method public boolean removeCallbacks(java.lang.Runnable); method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener); @@ -25773,7 +25826,8 @@ package android.webkit { method public deprecated void emulateShiftHeld(); method public static deprecated void enablePlatformNotifications(); method public static java.lang.String findAddress(java.lang.String); - method public int findAll(java.lang.String); + method public deprecated int findAll(java.lang.String); + method public void findAllAsync(java.lang.String); method public void findNext(boolean); method public void flingScroll(int, int); method public void freeMemory(); @@ -25789,7 +25843,6 @@ package android.webkit { method public java.lang.String getTitle(); method public java.lang.String getUrl(); method public deprecated int getVisibleTitleHeight(); - method public deprecated android.view.View getZoomControls(); method public void goBack(); method public void goBackOrForward(int); method public void goForward(); @@ -25824,6 +25877,7 @@ package android.webkit { method public void saveWebArchive(java.lang.String, boolean, android.webkit.ValueCallback<java.lang.String>); method public void setCertificate(android.net.http.SslCertificate); method public void setDownloadListener(android.webkit.DownloadListener); + method public void setFindListener(android.webkit.WebView.FindListener); method public void setHorizontalScrollbarOverlay(boolean); method public void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String); method public void setInitialScale(int); @@ -25842,6 +25896,10 @@ package android.webkit { field public static final java.lang.String SCHEME_TEL = "tel:"; } + public static abstract interface WebView.FindListener { + method public abstract void onFindResultReceived(int, int, boolean); + } + public static class WebView.HitTestResult { method public java.lang.String getExtra(); method public int getType(); @@ -42487,15 +42545,21 @@ package junit.framework { method public static void assertTrue(boolean); method public static void fail(java.lang.String); method public static void fail(); + method public static void failNotEquals(java.lang.String, java.lang.Object, java.lang.Object); + method public static void failNotSame(java.lang.String, java.lang.Object, java.lang.Object); + method public static void failSame(java.lang.String); + method public static java.lang.String format(java.lang.String, java.lang.Object, java.lang.Object); } - public class AssertionFailedError extends java.lang.Error { + public class AssertionFailedError extends java.lang.AssertionError { ctor public AssertionFailedError(); ctor public AssertionFailedError(java.lang.String); } public class ComparisonFailure extends junit.framework.AssertionFailedError { ctor public ComparisonFailure(java.lang.String, java.lang.String, java.lang.String); + method public java.lang.String getActual(); + method public java.lang.String getExpected(); } public abstract interface Protectable { @@ -42547,9 +42611,9 @@ package junit.framework { method public synchronized void addListener(junit.framework.TestListener); method public void endTest(junit.framework.Test); method public synchronized int errorCount(); - method public synchronized java.util.Enumeration errors(); + method public synchronized java.util.Enumeration<junit.framework.TestFailure> errors(); method public synchronized int failureCount(); - method public synchronized java.util.Enumeration failures(); + method public synchronized java.util.Enumeration<junit.framework.TestFailure> failures(); method public synchronized void removeListener(junit.framework.TestListener); method protected void run(junit.framework.TestCase); method public synchronized int runCount(); @@ -42566,21 +42630,24 @@ package junit.framework { public class TestSuite implements junit.framework.Test { ctor public TestSuite(); - ctor public TestSuite(java.lang.Class, java.lang.String); - ctor public TestSuite(java.lang.Class); + ctor public TestSuite(java.lang.Class<?>); + ctor public TestSuite(java.lang.Class<? extends junit.framework.TestCase>, java.lang.String); ctor public TestSuite(java.lang.String); + ctor public TestSuite(java.lang.Class<?>...); + ctor public TestSuite(java.lang.Class<? extends junit.framework.TestCase>[], java.lang.String); method public void addTest(junit.framework.Test); - method public void addTestSuite(java.lang.Class); + method public void addTestSuite(java.lang.Class<? extends junit.framework.TestCase>); method public int countTestCases(); - method public static junit.framework.Test createTest(java.lang.Class, java.lang.String); + method public static junit.framework.Test createTest(java.lang.Class<?>, java.lang.String); method public java.lang.String getName(); - method public static java.lang.reflect.Constructor getTestConstructor(java.lang.Class) throws java.lang.NoSuchMethodException; + method public static java.lang.reflect.Constructor<?> getTestConstructor(java.lang.Class<?>) throws java.lang.NoSuchMethodException; method public void run(junit.framework.TestResult); method public void runTest(junit.framework.Test, junit.framework.TestResult); method public void setName(java.lang.String); method public junit.framework.Test testAt(int); method public int testCount(); - method public java.util.Enumeration tests(); + method public java.util.Enumeration<junit.framework.Test> tests(); + method public static junit.framework.Test warning(java.lang.String); } } @@ -42597,13 +42664,13 @@ package junit.runner { method public java.lang.String extractClassName(java.lang.String); method public static java.lang.String getFilteredTrace(java.lang.Throwable); method public static java.lang.String getFilteredTrace(java.lang.String); - method public junit.runner.TestSuiteLoader getLoader(); + method public deprecated junit.runner.TestSuiteLoader getLoader(); method public static java.lang.String getPreference(java.lang.String); method public static int getPreference(java.lang.String, int); method protected static java.util.Properties getPreferences(); method public junit.framework.Test getTest(java.lang.String); - method public static boolean inVAJava(); - method protected java.lang.Class loadSuiteClass(java.lang.String) throws java.lang.ClassNotFoundException; + method public static deprecated boolean inVAJava(); + method protected java.lang.Class<?> loadSuiteClass(java.lang.String) throws java.lang.ClassNotFoundException; method protected java.lang.String processArguments(java.lang.String[]); method protected abstract void runFailed(java.lang.String); method public static void savePreferences() throws java.io.IOException; diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java index 3037881..fcf3c7e 100755 --- a/cmds/input/src/com/android/commands/input/Input.java +++ b/cmds/input/src/com/android/commands/input/Input.java @@ -145,13 +145,15 @@ public class Input { private void injectKeyEvent(KeyEvent event) { Log.i(TAG, "InjectKeyEvent: " + event); - InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); + InputManager.getInstance().injectInputEvent(event, + InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } private void injectPointerEvent(MotionEvent event) { event.setSource(InputDevice.SOURCE_TOUCHSCREEN); Log.i("Input", "InjectPointerEvent: " + event); - InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); + InputManager.getInstance().injectInputEvent(event, + InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } private static final float lerp(float a, float b, float alpha) { diff --git a/core/java/android/accounts/AccountAndUser.java b/core/java/android/accounts/AccountAndUser.java new file mode 100644 index 0000000..04157cc --- /dev/null +++ b/core/java/android/accounts/AccountAndUser.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.accounts; + +/** + * Used to store the Account and the UserId this account is associated with. + * + * @hide + */ +public class AccountAndUser { + public Account account; + public int userId; + + public AccountAndUser(Account account, int userId) { + this.account = account; + this.userId = userId; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AccountAndUser)) return false; + final AccountAndUser other = (AccountAndUser) o; + return this.account.equals(other.account) + && this.userId == other.userId; + } + + @Override + public int hashCode() { + return account.hashCode() + userId; + } + + public String toString() { + return account.toString() + " u" + userId; + } +} diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 197c1bd..2b643c2 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -1488,6 +1488,31 @@ public class AccountManagerService } } + /** + * Returns all the accounts qualified by user. + * @hide + */ + public AccountAndUser[] getAllAccounts() { + ArrayList<AccountAndUser> allAccounts = new ArrayList<AccountAndUser>(); + List<UserInfo> users = getAllUsers(); + if (users == null) return new AccountAndUser[0]; + + synchronized(mUsers) { + for (UserInfo user : users) { + UserAccounts userAccounts = getUserAccounts(user.id); + if (userAccounts == null) continue; + synchronized (userAccounts.cacheLock) { + Account[] accounts = getAccountsFromCacheLocked(userAccounts, null); + for (int a = 0; a < accounts.length; a++) { + allAccounts.add(new AccountAndUser(accounts[a], user.id)); + } + } + } + } + AccountAndUser[] accountsArray = new AccountAndUser[allAccounts.size()]; + return allAccounts.toArray(accountsArray); + } + public Account[] getAccounts(String type) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "getAccounts: accountType " + type @@ -1844,9 +1869,12 @@ public class AccountManagerService File systemDir = Environment.getSystemSecureDirectory(); File databaseFile = new File(systemDir, "users/" + userId + "/" + DATABASE_NAME); if (userId == 0) { - // Migrate old file, if it exists, to the new location + // Migrate old file, if it exists, to the new location. + // Make sure the new file doesn't already exist. A dummy file could have been + // accidentally created in the old location, causing the new one to become corrupted + // as well. File oldFile = new File(systemDir, DATABASE_NAME); - if (oldFile.exists()) { + if (oldFile.exists() && !databaseFile.exists()) { // Check for use directory; create if it doesn't exist, else renameTo will fail File userDir = new File(systemDir, "users/" + userId); if (!userDir.exists()) { diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index c5a4171..f9fa444 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -420,11 +420,7 @@ public final class AnimatorSet extends Animator { if (duration < 0) { throw new IllegalArgumentException("duration must be a value of zero or greater"); } - for (Node node : mNodes) { - // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to - // insert "play-after" delays - node.animation.setDuration(duration); - } + // Just record the value for now - it will be used later when the AnimatorSet starts mDuration = duration; return this; } @@ -456,6 +452,14 @@ public final class AnimatorSet extends Animator { mTerminated = false; mStarted = true; + if (mDuration >= 0) { + // If the duration was set on this AnimatorSet, pass it along to all child animations + for (Node node : mNodes) { + // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to + // insert "play-after" delays + node.animation.setDuration(mDuration); + } + } // First, sort the nodes (if necessary). This will ensure that sortedNodes // contains the animation nodes in the correct order. sortNodes(); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 3e123ba..1c820dc 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -55,6 +55,7 @@ import android.text.method.TextKeyListener; import android.util.AttributeSet; import android.util.EventLog; import android.util.Log; +import android.util.Slog; import android.util.SparseArray; import android.view.ActionMode; import android.view.ContextMenu; @@ -642,6 +643,7 @@ public class Activity extends ContextThemeWrapper Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2 { private static final String TAG = "Activity"; + private static final boolean DEBUG_LIFECYCLE = false; /** Standard activity result: operation canceled. */ public static final int RESULT_CANCELED = 0; @@ -865,6 +867,7 @@ public class Activity extends ContextThemeWrapper * @see #onPostCreate */ protected void onCreate(Bundle savedInstanceState) { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState); if (mLastNonConfigurationInstances != null) { mAllLoaderManagers = mLastNonConfigurationInstances.loaders; } @@ -1013,6 +1016,7 @@ public class Activity extends ContextThemeWrapper * @see #onResume */ protected void onStart() { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this); mCalled = true; if (!mLoadersStarted) { @@ -1073,6 +1077,7 @@ public class Activity extends ContextThemeWrapper * @see #onPause */ protected void onResume() { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this); getApplication().dispatchActivityResumed(this); mCalled = true; } @@ -1131,6 +1136,7 @@ public class Activity extends ContextThemeWrapper final void performSaveInstanceState(Bundle outState) { onSaveInstanceState(outState); saveManagedDialogs(outState); + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState); } /** @@ -1261,6 +1267,7 @@ public class Activity extends ContextThemeWrapper * @see #onStop */ protected void onPause() { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this); getApplication().dispatchActivityPaused(this); mCalled = true; } @@ -1347,6 +1354,7 @@ public class Activity extends ContextThemeWrapper * @see #onDestroy */ protected void onStop() { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this); if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false); getApplication().dispatchActivityStopped(this); mCalled = true; @@ -1381,6 +1389,7 @@ public class Activity extends ContextThemeWrapper * @see #isFinishing */ protected void onDestroy() { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this); mCalled = true; // dismiss any dialogs we are managing. @@ -1432,6 +1441,7 @@ public class Activity extends ContextThemeWrapper * @param newConfig The new device configuration. */ public void onConfigurationChanged(Configuration newConfig) { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onConfigurationChanged " + this + ": " + newConfig); mCalled = true; mFragments.dispatchConfigurationChanged(newConfig); @@ -1613,11 +1623,13 @@ public class Activity extends ContextThemeWrapper } public void onLowMemory() { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onLowMemory " + this); mCalled = true; mFragments.dispatchLowMemory(); } public void onTrimMemory(int level) { + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onTrimMemory " + this + ": " + level); mCalled = true; mFragments.dispatchTrimMemory(level); } @@ -2522,7 +2534,19 @@ public class Activity extends ContextThemeWrapper if (onOptionsItemSelected(item)) { return true; } - return mFragments.dispatchOptionsItemSelected(item); + if (mFragments.dispatchOptionsItemSelected(item)) { + return true; + } + if (item.getItemId() == android.R.id.home && mActionBar != null && + (mActionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) { + if (mParent == null) { + onNavigateUp(); + } else { + mParent.onNavigateUpFromChild(this); + } + return true; + } + return false; case Window.FEATURE_CONTEXT_MENU: EventLog.writeEvent(50000, 1, item.getTitleCondensed()); @@ -2654,15 +2678,6 @@ public class Activity extends ContextThemeWrapper if (mParent != null) { return mParent.onOptionsItemSelected(item); } - if (item.getItemId() == android.R.id.home && mActionBar != null && - (mActionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) { - if (mParent == null) { - onNavigateUp(); - } else { - mParent.onNavigateUpFromChild(this); - } - return true; - } return false; } @@ -4641,7 +4656,7 @@ public class Activity extends ContextThemeWrapper /** * Print the Activity's state into the given stream. This gets invoked if - * you run "adb shell dumpsys activity <activity_component_name>". + * you run "adb shell dumpsys activity <activity_component_name>". * * @param prefix Desired prefix to prepend at each line of output. * @param fd The raw file descriptor that the dump is being sent to. @@ -4865,11 +4880,19 @@ public class Activity extends ContextThemeWrapper * Obtain an {@link Intent} that will launch an explicit target activity specified by * this activity's logical parent. The logical parent is named in the application's manifest * by the {@link android.R.attr#parentActivityName parentActivityName} attribute. + * Activity subclasses may override this method to modify the Intent returned by + * super.getParentActivityIntent() or to implement a different mechanism of retrieving + * the parent intent entirely. * - * @return a new Intent targeting the defined parent of this activity + * @return a new Intent targeting the defined parent of this activity or null if + * there is no valid parent. */ public Intent getParentActivityIntent() { - return new Intent().setClassName(this, mActivityInfo.parentActivityName); + final String parentName = mActivityInfo.parentActivityName; + if (TextUtils.isEmpty(parentName)) { + return null; + } + return new Intent().setClassName(this, parentName); } // ------------------ Internal API ------------------ diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index a3fdf3e..7e1589f 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1000,7 +1000,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM } return true; } - + case GOING_TO_SLEEP_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); goingToSleep(); @@ -1015,6 +1015,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case SET_LOCK_SCREEN_SHOWN_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + setLockScreenShown(data.readInt() != 0); + reply.writeNoException(); + return true; + } + case SET_DEBUG_APP_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String pn = data.readString(); @@ -2912,6 +2919,17 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } + public void setLockScreenShown(boolean shown) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(shown ? 1 : 0); + mRemote.transact(SET_LOCK_SCREEN_SHOWN_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } public void setDebugApp( String packageName, boolean waitForDebugger, boolean persistent) throws RemoteException diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index c637df0..c3cceaf 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -21,7 +21,6 @@ import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.os.IRemoteCallback; -import android.os.Message; import android.os.RemoteException; import android.view.View; @@ -121,6 +120,7 @@ public class ActivityOptions { /** * Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation} * to find out when the given animation has started running. + * @hide */ public interface OnAnimationStartedListener { void onAnimationStarted(); @@ -137,11 +137,31 @@ public class ActivityOptions { * of the animation. * @param startX The x starting location of the bitmap, in screen coordiantes. * @param startY The y starting location of the bitmap, in screen coordinates. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + */ + public static ActivityOptions makeThumbnailScaleUpAnimation(View source, + Bitmap thumbnail, int startX, int startY) { + return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, null); + } + + /** + * Create an ActivityOptions specifying an animation where a thumbnail + * is scaled from a given position to the new activity window that is + * being started. + * + * @param source The View that this thumbnail is animating from. This + * defines the coordinate space for <var>startX</var> and <var>startY</var>. + * @param thumbnail The bitmap that will be shown as the initial thumbnail + * of the animation. + * @param startX The x starting location of the bitmap, in screen coordiantes. + * @param startY The y starting location of the bitmap, in screen coordinates. * @param listener Optional OnAnimationStartedListener to find out when the * requested animation has started running. If for some reason the animation * is not executed, the callback will happen immediately. * @return Returns a new ActivityOptions object that you can use to * supply these options as the options Bundle when starting an activity. + * @hide */ public static ActivityOptions makeThumbnailScaleUpAnimation(View source, Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 98c4e10..1489b2c 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -138,6 +138,7 @@ public final class ActivityThread { private static final boolean DEBUG_BACKUP = true; private static final boolean DEBUG_CONFIGURATION = false; private static final boolean DEBUG_SERVICE = false; + private static final boolean DEBUG_MEMORY_TRIM = false; private static final long MIN_TIME_BETWEEN_GCS = 5*1000; private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; @@ -2779,9 +2780,21 @@ public final class ActivityThread { performStopActivityInner(r, null, false, saveState); } - private static class StopInfo { + private static class StopInfo implements Runnable { + ActivityClientRecord activity; + Bundle state; Bitmap thumbnail; CharSequence description; + + @Override public void run() { + // Tell activity manager we have been stopped. + try { + if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity); + ActivityManagerNative.getDefault().activityStopped( + activity.token, state, thumbnail, description); + } catch (RemoteException ex) { + } + } } private static final class ProviderRefCount { @@ -2911,12 +2924,14 @@ public final class ActivityThread { QueuedWork.waitToFinish(); } - // Tell activity manager we have been stopped. - try { - ActivityManagerNative.getDefault().activityStopped( - r.token, r.state, info.thumbnail, info.description); - } catch (RemoteException ex) { - } + // Schedule the call to tell the activity manager we have + // stopped. We don't do this immediately, because we want to + // have a chance for any other pending work (in particular memory + // trim requests) to complete before you tell the activity + // manager to proceed and allow us to go fully into the background. + info.activity = r; + info.state = r.state; + mH.post(info); } final void performRestartActivity(IBinder token) { @@ -3749,6 +3764,7 @@ public final class ActivityThread { } final void handleTrimMemory(int level) { + if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level); WindowManagerImpl.getDefault().trimMemory(level); ArrayList<ComponentCallbacks2> callbacks; diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index c5d7b91..138a88f 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -325,9 +325,9 @@ class ContextImpl extends Context { return createDropBoxManager(); }}); - registerService(INPUT_SERVICE, new ServiceFetcher() { - public Object createService(ContextImpl ctx) { - return new InputManager(ctx); + registerService(INPUT_SERVICE, new StaticServiceFetcher() { + public Object createStaticService() { + return InputManager.getInstance(); }}); registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() { diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index c493f0f..d3ba497 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -203,7 +203,7 @@ final class FragmentState implements Parcelable { * <li> {@link #onCreateView} creates and returns the view hierarchy associated * with the fragment. * <li> {@link #onActivityCreated} tells the fragment that its activity has - * completed its own {@link Activity#onCreate Activity.onCreaate}. + * completed its own {@link Activity#onCreate Activity.onCreate()}. * <li> {@link #onStart} makes the fragment visible to the user (based on its * containing activity being started). * <li> {@link #onResume} makes the fragment interacting with the user (based on its diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index c71b186..3fc2280 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -205,7 +205,8 @@ public interface IActivityManager extends IInterface { // Note: probably don't want to allow applications access to these. public void goingToSleep() throws RemoteException; public void wakingUp() throws RemoteException; - + public void setLockScreenShown(boolean shown) throws RemoteException; + public void unhandledBack() throws RemoteException; public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException; public void setDebugApp( @@ -588,4 +589,5 @@ public interface IActivityManager extends IInterface { int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144; int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145; int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146; + int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147; } diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index f955713..75c6e11 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -883,7 +883,7 @@ public class Instrumentation { } KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source); - InputManager.injectInputEvent(newEvent, + InputManager.getInstance().injectInputEvent(newEvent, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } @@ -926,7 +926,8 @@ public class Instrumentation { if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { event.setSource(InputDevice.SOURCE_TOUCHSCREEN); } - InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); + InputManager.getInstance().injectInputEvent(event, + InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } /** @@ -945,7 +946,8 @@ public class Instrumentation { if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) { event.setSource(InputDevice.SOURCE_TRACKBALL); } - InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); + InputManager.getInstance().injectInputEvent(event, + InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); } /** diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 207ae76..cb43d4c 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -666,8 +666,8 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac /** * Print the Service's state into the given stream. This gets invoked if - * you run "adb shell dumpsys activity service <yourservicename>". - * This is distinct from "dumpsys <servicename>", which only works for + * you run "adb shell dumpsys activity service <yourservicename>". + * This is distinct from "dumpsys <servicename>", which only works for * named system services and which invokes the {@link IBinder#dump} method * on the {@link IBinder} interface registered with ServiceManager. * diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 05ef194..1206056 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -1127,7 +1127,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { /** * Print the Provider's state into the given stream. This gets invoked if - * you run "adb shell dumpsys activity provider <provider_component_name>". + * you run "adb shell dumpsys activity provider <provider_component_name>". * * @param prefix Desired prefix to prepend at each line of output. * @param fd The raw file descriptor that the dump is being sent to. diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 736dd24..18d682d 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2000,8 +2000,8 @@ public class Intent implements Parcelable, Cloneable { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_USB_ANLG_HEADSET_PLUG = - "android.intent.action.USB_ANLG_HEADSET_PLUG"; + public static final String ACTION_ANALOG_AUDIO_DOCK_PLUG = + "android.intent.action.ANALOG_AUDIO_DOCK_PLUG"; /** * Broadcast Action: A digital audio speaker/headset plugged in or unplugged. @@ -2015,8 +2015,8 @@ public class Intent implements Parcelable, Cloneable { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_USB_DGTL_HEADSET_PLUG = - "android.intent.action.USB_DGTL_HEADSET_PLUG"; + public static final String ACTION_DIGITAL_AUDIO_DOCK_PLUG = + "android.intent.action.DIGITAL_AUDIO_DOCK_PLUG"; /** * Broadcast Action: A HMDI cable was plugged or unplugged @@ -2034,7 +2034,7 @@ public class Intent implements Parcelable, Cloneable { "android.intent.action.HDMI_AUDIO_PLUG"; /** - * Broadcast Action: A USB audio device was plugged in or unplugged. + * Broadcast Action: A USB audio accessory was plugged in or unplugged. * * <p>The intent will have the following extra values: * <ul> @@ -2046,11 +2046,11 @@ public class Intent implements Parcelable, Cloneable { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_USB_AUDIO_DEVICE_PLUG = - "android.intent.action.USB_AUDIO_DEVICE_PLUG"; + public static final String ACTION_USB_AUDIO_ACCESSORY_PLUG = + "android.intent.action.USB_AUDIO_ACCESSORY_PLUG"; /** - * Broadcast Action: A USB audio accessory was plugged in or unplugged. + * Broadcast Action: A USB audio device was plugged in or unplugged. * * <p>The intent will have the following extra values: * <ul> @@ -2062,8 +2062,8 @@ public class Intent implements Parcelable, Cloneable { * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_USB_AUDIO_ACCESSORY_PLUG = - "android.intent.action.USB_AUDIO_ACCESSORY_PLUG"; + public static final String ACTION_USB_AUDIO_DEVICE_PLUG = + "android.intent.action.USB_AUDIO_DEVICE_PLUG"; /** * <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p> diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index 06dfe90..34c40a0 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -22,6 +22,7 @@ import com.google.android.collect.Lists; import com.google.android.collect.Maps; import android.accounts.Account; +import android.accounts.AccountAndUser; import android.accounts.AccountManager; import android.accounts.AccountManagerService; import android.accounts.OnAccountsUpdateListener; @@ -204,6 +205,9 @@ public class SyncManager implements OnAccountsUpdateListener { private final PowerManager mPowerManager; + // Use this as a random offset to seed all periodic syncs + private int mSyncRandomOffsetMillis; + private static final long SYNC_ALARM_TIMEOUT_MIN = 30 * 1000; // 30 seconds private static final long SYNC_ALARM_TIMEOUT_MAX = 2 * 60 * 60 * 1000; // two hours @@ -237,22 +241,14 @@ public class SyncManager implements OnAccountsUpdateListener { int count = 0; - // For all known users on the system, get their accounts and add them to the list + // Get accounts from AccountManager for all the users on the system // TODO: Limit this to active users, when such a concept exists. + AccountAndUser[] allAccounts = AccountManagerService.getSingleton().getAllAccounts(); for (UserInfo user : users) { - accounts = AccountManagerService.getSingleton().getAccounts(user.id); - count += accounts.length; - } - - AccountAndUser[] allAccounts = new AccountAndUser[count]; - int index = 0; - for (UserInfo user : users) { - accounts = AccountManagerService.getSingleton().getAccounts(user.id); - for (Account account : accounts) { - allAccounts[index++] = new AccountAndUser(account, user.id); - } if (mBootCompleted) { - mSyncStorageEngine.doDatabaseCleanup(accounts, user.id); + Account[] accountsForUser = + AccountManagerService.getSingleton().getAccounts(user.id); + mSyncStorageEngine.doDatabaseCleanup(accountsForUser, user.id); } } @@ -338,33 +334,6 @@ public class SyncManager implements OnAccountsUpdateListener { private volatile boolean mBootCompleted = false; - static class AccountAndUser { - Account account; - int userId; - - AccountAndUser(Account account, int userId) { - this.account = account; - this.userId = userId; - } - - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof AccountAndUser)) return false; - final AccountAndUser other = (AccountAndUser) o; - return this.account.equals(other.account) - && this.userId == other.userId; - } - - @Override - public int hashCode() { - return account.hashCode() + userId; - } - - public String toString() { - return account.toString() + " u" + userId; - } - } - private ConnectivityManager getConnectivityManager() { synchronized (this) { if (mConnManagerDoNotUseDirectly == null) { @@ -472,6 +441,9 @@ public class SyncManager implements OnAccountsUpdateListener { // do this synchronously to ensure we have the accounts before this call returns onAccountsUpdated(null); } + + // Pick a random second in a day to seed all periodic syncs + mSyncRandomOffsetMillis = mSyncStorageEngine.getSyncRandomOffset() * 1000; } /** @@ -700,6 +672,7 @@ public class SyncManager implements OnAccountsUpdateListener { private void sendCheckAlarmsMessage() { if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_CHECK_ALARMS"); + mSyncHandler.removeMessages(SyncHandler.MESSAGE_CHECK_ALARMS); mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS); } @@ -748,6 +721,8 @@ public class SyncManager implements OnAccountsUpdateListener { } private void increaseBackoffSetting(SyncOperation op) { + // TODO: Use this function to align it to an already scheduled sync + // operation in the specified window final long now = SystemClock.elapsedRealtime(); final Pair<Long, Long> previousSettings = @@ -1094,6 +1069,8 @@ public class SyncManager implements OnAccountsUpdateListener { final long now = SystemClock.elapsedRealtime(); pw.print("now: "); pw.print(now); pw.println(" (" + formatTime(System.currentTimeMillis()) + ")"); + pw.print("offset: "); pw.print(DateUtils.formatElapsedTime(mSyncRandomOffsetMillis/1000)); + pw.println(" (HH:MM:SS)"); pw.print("uptime: "); pw.print(DateUtils.formatElapsedTime(now/1000)); pw.println(" (HH:MM:SS)"); pw.print("time spent syncing: "); @@ -1805,6 +1782,9 @@ public class SyncManager implements OnAccountsUpdateListener { AccountAndUser[] accounts = mAccounts; final long nowAbsolute = System.currentTimeMillis(); + final long shiftedNowAbsolute = (0 < nowAbsolute - mSyncRandomOffsetMillis) + ? (nowAbsolute - mSyncRandomOffsetMillis) : 0; + ArrayList<SyncStorageEngine.AuthorityInfo> infos = mSyncStorageEngine.getAuthorities(); for (SyncStorageEngine.AuthorityInfo info : infos) { // skip the sync if the account of this operation no longer exists @@ -1826,16 +1806,32 @@ public class SyncManager implements OnAccountsUpdateListener { SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(info); for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) { final Bundle extras = info.periodicSyncs.get(i).first; - final Long periodInSeconds = info.periodicSyncs.get(i).second; + final Long periodInMillis = info.periodicSyncs.get(i).second * 1000; // find when this periodic sync was last scheduled to run final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i); - // compute when this periodic sync should next run - this can be in the future - // for example if the user changed the time, synced and changed back. - final long nextPollTimeAbsolute = lastPollTimeAbsolute > nowAbsolute - ? nowAbsolute - : lastPollTimeAbsolute + periodInSeconds * 1000; - // if it is ready to run then schedule it and mark it as having been scheduled - if (nextPollTimeAbsolute <= nowAbsolute) { + + long remainingMillis + = periodInMillis - (shiftedNowAbsolute % periodInMillis); + + /* + * Sync scheduling strategy: + * Set the next periodic sync based on a random offset (in seconds). + * + * Also sync right now if any of the following cases hold + * and mark it as having been scheduled + * + * Case 1: This sync is ready to run now. + * Case 2: If the lastPollTimeAbsolute is in the future, + * sync now and reinitialize. This can happen for + * example if the user changed the time, synced and + * changed back. + * Case 3: If we failed to sync at the last scheduled time + */ + if (remainingMillis == periodInMillis // Case 1 + || lastPollTimeAbsolute > nowAbsolute // Case 2 + || (nowAbsolute - lastPollTimeAbsolute + >= periodInMillis)) { // Case 3 + // Sync now final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff( info.account, info.userId, info.authority); final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo = @@ -1853,12 +1849,13 @@ public class SyncManager implements OnAccountsUpdateListener { info.account, info.userId, info.authority), syncAdapterInfo.type.allowParallelSyncs())); status.setPeriodicSyncTime(i, nowAbsolute); - } else { - // it isn't ready to run, remember this time if it is earlier than - // earliestFuturePollTime - if (nextPollTimeAbsolute < earliestFuturePollTime) { - earliestFuturePollTime = nextPollTimeAbsolute; - } + } + // Compute when this periodic sync should next run + final long nextPollTimeAbsolute = nowAbsolute + remainingMillis; + + // remember this time if it is earlier than earliestFuturePollTime + if (nextPollTimeAbsolute < earliestFuturePollTime) { + earliestFuturePollTime = nextPollTimeAbsolute; } } } diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index 9c81c9e..d821918 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -25,7 +25,7 @@ import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.accounts.Account; -import android.content.SyncManager.AccountAndUser; +import android.accounts.AccountAndUser; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; @@ -37,6 +37,7 @@ import android.os.Message; import android.os.Parcel; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.SystemClock; import android.util.Log; import android.util.SparseArray; import android.util.Xml; @@ -49,6 +50,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; +import java.util.Random; import java.util.TimeZone; import java.util.List; @@ -65,6 +67,7 @@ public class SyncStorageEngine extends Handler { private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId"; private static final String XML_ATTR_LISTEN_FOR_TICKLES = "listen-for-tickles"; + private static final String XML_ATTR_SYNC_RANDOM_OFFSET = "offsetInSeconds"; private static final String XML_ATTR_ENABLED = "enabled"; private static final String XML_ATTR_USER = "user"; private static final String XML_TAG_LISTEN_FOR_TICKLES = "listenForTickles"; @@ -277,6 +280,8 @@ public class SyncStorageEngine extends Handler { private static volatile SyncStorageEngine sSyncStorageEngine = null; + private int mSyncRandomOffset; + /** * This file contains the core engine state: all accounts and the * settings for them. It must never be lost, and should be changed @@ -375,6 +380,10 @@ public class SyncStorageEngine extends Handler { } } + public int getSyncRandomOffset() { + return mSyncRandomOffset; + } + public void addStatusChangeListener(int mask, ISyncStatusObserver callback) { synchronized (mAuthorities) { mChangeListeners.register(callback, mask); @@ -1465,6 +1474,16 @@ public class SyncStorageEngine extends Handler { } catch (NumberFormatException e) { // don't care } + String offsetString = parser.getAttributeValue(null, XML_ATTR_SYNC_RANDOM_OFFSET); + try { + mSyncRandomOffset = (offsetString == null) ? 0 : Integer.parseInt(offsetString); + } catch (NumberFormatException e) { + mSyncRandomOffset = 0; + } + if (mSyncRandomOffset == 0) { + Random random = new Random(System.currentTimeMillis()); + mSyncRandomOffset = random.nextInt(86400); + } mMasterSyncAutomatically.put(0, listen == null || Boolean.parseBoolean(listen)); eventType = parser.next(); AuthorityInfo authority = null; @@ -1705,6 +1724,7 @@ public class SyncStorageEngine extends Handler { out.startTag(null, "accounts"); out.attribute(null, "version", Integer.toString(ACCOUNTS_VERSION)); out.attribute(null, XML_ATTR_NEXT_AUTHORITY_ID, Integer.toString(mNextAuthorityId)); + out.attribute(null, XML_ATTR_SYNC_RANDOM_OFFSET, Integer.toString(mSyncRandomOffset)); // Write the Sync Automatically flags for each user final int M = mMasterSyncAutomatically.size(); diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index 415d58a..85f7aa5 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -154,7 +154,7 @@ public class PackageInfo implements Parcelable { /** * Flag for {@link #requestedPermissionsFlags}: the requested permission * is required for the application to run; the user can not optionally - * disable it. + * disable it. Currently all permissions are required. */ public static final int REQUESTED_PERMISSION_REQUIRED = 1<<0; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index b06b4a5..5d890d4 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1095,6 +1095,18 @@ public abstract class PackageManager { /** {@hide} */ public static final int ENFORCEMENT_YES = 1; + /** {@hide} */ + public static String enforcementToString(int enforcement) { + switch (enforcement) { + case ENFORCEMENT_DEFAULT: + return "DEFAULT"; + case ENFORCEMENT_YES: + return "YES"; + default: + return Integer.toString(enforcement); + } + } + /** * Retrieve overall information about an application package that is * installed on the system. diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 7571993..b6ebbdf 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -989,14 +989,16 @@ public class PackageParser { // that may change. String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesPermission_name); + /* Not supporting optional permissions yet. boolean required = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestUsesPermission_required, true); + */ sa.recycle(); if (name != null && !pkg.requestedPermissions.contains(name)) { pkg.requestedPermissions.add(name.intern()); - pkg.requestedPermissionsRequired.add(required ? Boolean.TRUE : Boolean.FALSE); + pkg.requestedPermissionsRequired.add(Boolean.TRUE); } XmlUtils.skipCurrentTag(parser); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 2af58be..c682852 100755 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -32,7 +32,6 @@ import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.util.Slog; -import android.util.SparseArray; import android.util.TypedValue; import android.util.LongSparseArray; @@ -86,8 +85,8 @@ public class Resources { // single-threaded, and after that these are immutable. private static final LongSparseArray<Drawable.ConstantState> sPreloadedDrawables = new LongSparseArray<Drawable.ConstantState>(); - private static final SparseArray<ColorStateList> mPreloadedColorStateLists - = new SparseArray<ColorStateList>(); + private static final LongSparseArray<ColorStateList> sPreloadedColorStateLists + = new LongSparseArray<ColorStateList>(); private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables = new LongSparseArray<Drawable.ConstantState>(); private static boolean mPreloaded; @@ -98,8 +97,8 @@ public class Resources { // These are protected by the mTmpValue lock. private final LongSparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache = new LongSparseArray<WeakReference<Drawable.ConstantState> >(); - private final SparseArray<WeakReference<ColorStateList> > mColorStateListCache - = new SparseArray<WeakReference<ColorStateList> >(); + private final LongSparseArray<WeakReference<ColorStateList> > mColorStateListCache + = new LongSparseArray<WeakReference<ColorStateList> >(); private final LongSparseArray<WeakReference<Drawable.ConstantState> > mColorDrawableCache = new LongSparseArray<WeakReference<Drawable.ConstantState> >(); private boolean mPreloading; @@ -118,22 +117,6 @@ public class Resources { private CompatibilityInfo mCompatibilityInfo; - private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>(0) { - @Override - public void put(long k, Object o) { - throw new UnsupportedOperationException(); - } - @Override - public void append(long k, Object o) { - throw new UnsupportedOperationException(); - } - }; - - @SuppressWarnings("unchecked") - private static <T> LongSparseArray<T> emptySparseArray() { - return (LongSparseArray<T>) EMPTY_ARRAY; - } - /** @hide */ public static int selectDefaultTheme(int curTheme, int targetSdkVersion) { return selectSystemTheme(curTheme, targetSdkVersion, @@ -180,9 +163,8 @@ public class Resources { * @param config Desired device configuration to consider when * selecting/computing resource values (optional). */ - public Resources(AssetManager assets, DisplayMetrics metrics, - Configuration config) { - this(assets, metrics, config, (CompatibilityInfo) null); + public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) { + this(assets, metrics, config, null); } /** @@ -1883,7 +1865,8 @@ public class Resources { return dr; } - Drawable.ConstantState cs = isColorDrawable ? sPreloadedColorDrawables.get(key) : sPreloadedDrawables.get(key); + Drawable.ConstantState cs = isColorDrawable ? + sPreloadedColorDrawables.get(key) : sPreloadedDrawables.get(key); if (cs != null) { dr = cs.newDrawable(this); } else { @@ -2005,21 +1988,21 @@ public class Resources { } } - final int key = (value.assetCookie << 24) | value.data; + final long key = (((long) value.assetCookie) << 32) | value.data; ColorStateList csl; if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT && value.type <= TypedValue.TYPE_LAST_COLOR_INT) { - csl = mPreloadedColorStateLists.get(key); + csl = sPreloadedColorStateLists.get(key); if (csl != null) { return csl; } csl = ColorStateList.valueOf(value.data); if (mPreloading) { - mPreloadedColorStateLists.put(key, csl); + sPreloadedColorStateLists.put(key, csl); } return csl; @@ -2030,7 +2013,7 @@ public class Resources { return csl; } - csl = mPreloadedColorStateLists.get(key); + csl = sPreloadedColorStateLists.get(key); if (csl != null) { return csl; } @@ -2063,14 +2046,13 @@ public class Resources { if (csl != null) { if (mPreloading) { - mPreloadedColorStateLists.put(key, csl); + sPreloadedColorStateLists.put(key, csl); } else { synchronized (mTmpValue) { //Log.i(TAG, "Saving cached color state list @ #" + // Integer.toHexString(key.intValue()) // + " in " + this + ": " + csl); - mColorStateListCache.put( - key, new WeakReference<ColorStateList>(csl)); + mColorStateListCache.put(key, new WeakReference<ColorStateList>(csl)); } } } @@ -2078,7 +2060,7 @@ public class Resources { return csl; } - private ColorStateList getCachedColorStateList(int key) { + private ColorStateList getCachedColorStateList(long key) { synchronized (mTmpValue) { WeakReference<ColorStateList> wr = mColorStateListCache.get(key); if (wr != null) { // we have the key @@ -2088,8 +2070,7 @@ public class Resources { // Integer.toHexString(((Integer)key).intValue()) // + " in " + this + ": " + entry); return entry; - } - else { // our entry has been purged + } else { // our entry has been purged mColorStateListCache.delete(key); } } diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index c2abce5..47e0d1e 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -16,6 +16,7 @@ package android.hardware.input; +import android.hardware.input.KeyboardLayout; import android.view.InputDevice; import android.view.InputEvent; @@ -34,4 +35,11 @@ interface IInputManager { // Injects an input event into the system. To inject into windows owned by other // applications, the caller must have the INJECT_EVENTS permission. boolean injectInputEvent(in InputEvent ev, int mode); + + // Keyboard layouts configuration. + KeyboardLayout[] getKeyboardLayouts(); + KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor); + String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor); + void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor, + String keyboardLayoutDescriptor); } diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 5ead1f4..3b3c237 100755 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -16,37 +16,18 @@ package android.hardware.input; -import com.android.internal.util.XmlUtils; - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.os.Bundle; import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Log; +import android.util.SparseArray; import android.view.InputDevice; import android.view.InputEvent; -import android.view.KeyCharacterMap; -import android.view.KeyCharacterMap.UnavailableException; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; /** * Provides information about input devices and available key layouts. @@ -60,13 +41,10 @@ import java.util.List; public final class InputManager { private static final String TAG = "InputManager"; - private static final IInputManager sIm; - - private final Context mContext; + private static InputManager sInstance; - // Used to simulate a persistent data store. - // TODO: Replace with the real thing. - private static final HashMap<String, String> mFakeRegistry = new HashMap<String, String>(); + private final IInputManager mIm; + private final SparseArray<InputDevice> mInputDevices = new SparseArray<InputDevice>(); /** * Broadcast Action: Query available keyboard layouts. @@ -169,14 +147,25 @@ public final class InputManager { */ public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; // see InputDispatcher.h - static { - IBinder b = ServiceManager.getService(Context.INPUT_SERVICE); - sIm = IInputManager.Stub.asInterface(b); + private InputManager(IInputManager im) { + mIm = im; } - /** @hide */ - public InputManager(Context context) { - mContext = context; + /** + * Gets an instance of the input manager. + * + * @return The input manager instance. + * + * @hide + */ + public static InputManager getInstance() { + synchronized (InputManager.class) { + if (sInstance == null) { + IBinder b = ServiceManager.getService(Context.INPUT_SERVICE); + sInstance = new InputManager(IInputManager.Stub.asInterface(b)); + } + return sInstance; + } } /** @@ -188,18 +177,16 @@ public final class InputManager { * </p> * * @return A list of all supported keyboard layouts. + * * @hide */ - public List<KeyboardLayout> getKeyboardLayouts() { - ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>(); - - final PackageManager pm = mContext.getPackageManager(); - Intent intent = new Intent(ACTION_QUERY_KEYBOARD_LAYOUTS); - for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent, - PackageManager.GET_META_DATA)) { - loadKeyboardLayouts(pm, resolveInfo.activityInfo, list, null); + public KeyboardLayout[] getKeyboardLayouts() { + try { + return mIm.getKeyboardLayouts(); + } catch (RemoteException ex) { + Log.w(TAG, "Could not get list of keyboard layout informations.", ex); + return new KeyboardLayout[0]; } - return list; } /** @@ -216,20 +203,10 @@ public final class InputManager { throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null"); } - KeyboardLayoutDescriptor d = parseKeyboardLayoutDescriptor(keyboardLayoutDescriptor); - if (d == null) { - return null; - } - - final PackageManager pm = mContext.getPackageManager(); try { - ActivityInfo receiver = pm.getReceiverInfo( - new ComponentName(d.packageName, d.receiverName), - PackageManager.GET_META_DATA); - return loadKeyboardLayouts(pm, receiver, null, d.keyboardLayoutName); - } catch (NameNotFoundException ex) { - Log.w(TAG, "Could not load keyboard layout '" + d.keyboardLayoutName - + "' from receiver " + d.packageName + "/" + d.receiverName, ex); + return mIm.getKeyboardLayout(keyboardLayoutDescriptor); + } catch (RemoteException ex) { + Log.w(TAG, "Could not get keyboard layout information.", ex); return null; } } @@ -243,12 +220,17 @@ public final class InputManager { * * @hide */ - public String getInputDeviceKeyboardLayoutDescriptor(String inputDeviceDescriptor) { + public String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor) { if (inputDeviceDescriptor == null) { throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); } - return mFakeRegistry.get(inputDeviceDescriptor); + try { + return mIm.getKeyboardLayoutForInputDevice(inputDeviceDescriptor); + } catch (RemoteException ex) { + Log.w(TAG, "Could not get keyboard layout for input device.", ex); + return null; + } } /** @@ -264,92 +246,17 @@ public final class InputManager { * * @hide */ - public void setInputDeviceKeyboardLayoutDescriptor(String inputDeviceDescriptor, + public void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor, String keyboardLayoutDescriptor) { if (inputDeviceDescriptor == null) { throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); } - mFakeRegistry.put(inputDeviceDescriptor, keyboardLayoutDescriptor); - } - - private KeyboardLayout loadKeyboardLayouts( - PackageManager pm, ActivityInfo receiver, - List<KeyboardLayout> list, String keyboardName) { - Bundle metaData = receiver.metaData; - if (metaData == null) { - return null; - } - - int configResId = metaData.getInt(META_DATA_KEYBOARD_LAYOUTS); - if (configResId == 0) { - Log.w(TAG, "Missing meta-data '" + META_DATA_KEYBOARD_LAYOUTS + "' on receiver " - + receiver.packageName + "/" + receiver.name); - return null; - } - try { - Resources resources = pm.getResourcesForApplication(receiver.applicationInfo); - XmlResourceParser parser = resources.getXml(configResId); - try { - XmlUtils.beginDocument(parser, "keyboard-layouts"); - - for (;;) { - XmlUtils.nextElement(parser); - String element = parser.getName(); - if (element == null) { - break; - } - if (element.equals("keyboard-layout")) { - TypedArray a = resources.obtainAttributes( - parser, com.android.internal.R.styleable.KeyboardLayout); - try { - String name = a.getString( - com.android.internal.R.styleable.KeyboardLayout_name); - String label = a.getString( - com.android.internal.R.styleable.KeyboardLayout_label); - int kcmResId = a.getResourceId( - com.android.internal.R.styleable.KeyboardLayout_kcm, 0); - if (name == null || label == null || kcmResId == 0) { - Log.w(TAG, "Missing required 'name', 'label' or 'kcm' " - + "attributes in keyboard layout " - + "resource from receiver " - + receiver.packageName + "/" + receiver.name); - } else { - String descriptor = makeKeyboardLayoutDescriptor( - receiver.packageName, receiver.name, name); - KeyboardLayout c = new KeyboardLayout( - descriptor, label, kcmResId); - if (keyboardName != null && name.equals(keyboardName)) { - return c; - } - if (list != null) { - list.add(c); - } - } - } finally { - a.recycle(); - } - } else { - Log.w(TAG, "Skipping unrecognized element '" + element - + "' in keyboard layout resource from receiver " - + receiver.packageName + "/" + receiver.name); - } - } - } finally { - parser.close(); - } - } catch (Exception ex) { - Log.w(TAG, "Could not load keyboard layout resource from receiver " - + receiver.packageName + "/" + receiver.name, ex); - return null; - } - if (keyboardName != null) { - Log.w(TAG, "Could not load keyboard layout '" + keyboardName - + "' from receiver " + receiver.packageName + "/" + receiver.name - + " because it was not declared in the keyboard layout resource."); + mIm.setKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor); + } catch (RemoteException ex) { + Log.w(TAG, "Could not set keyboard layout for input device.", ex); } - return null; } /** @@ -359,15 +266,16 @@ public final class InputManager { * speed set by {@link #tryPointerSpeed}. * </p> * + * @param context The application context. * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}. * * @hide */ - public int getPointerSpeed() { + public int getPointerSpeed(Context context) { int speed = DEFAULT_POINTER_SPEED; try { - speed = Settings.System.getInt(mContext.getContentResolver(), + speed = Settings.System.getInt(context.getContentResolver(), Settings.System.POINTER_SPEED); } catch (SettingNotFoundException snfe) { } @@ -380,17 +288,18 @@ public final class InputManager { * Requires {@link android.Manifest.permissions.WRITE_SETTINGS}. * </p> * + * @param context The application context. * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}. * * @hide */ - public void setPointerSpeed(int speed) { + public void setPointerSpeed(Context context, int speed) { if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) { throw new IllegalArgumentException("speed out of range"); } - Settings.System.putInt(mContext.getContentResolver(), + Settings.System.putInt(context.getContentResolver(), Settings.System.POINTER_SPEED, speed); } @@ -411,7 +320,7 @@ public final class InputManager { } try { - sIm.tryPointerSpeed(speed); + mIm.tryPointerSpeed(speed); } catch (RemoteException ex) { Log.w(TAG, "Could not set temporary pointer speed.", ex); } @@ -424,12 +333,27 @@ public final class InputManager { * * @hide */ - public static InputDevice getInputDevice(int id) { + public InputDevice getInputDevice(int id) { + synchronized (mInputDevices) { + InputDevice inputDevice = mInputDevices.get(id); + if (inputDevice != null) { + return inputDevice; + } + } + final InputDevice newInputDevice; try { - return sIm.getInputDevice(id); + newInputDevice = mIm.getInputDevice(id); } catch (RemoteException ex) { throw new RuntimeException("Could not get input device information.", ex); } + synchronized (mInputDevices) { + InputDevice inputDevice = mInputDevices.get(id); + if (inputDevice != null) { + return inputDevice; + } + mInputDevices.put(id, newInputDevice); + return newInputDevice; + } } /** @@ -438,9 +362,9 @@ public final class InputManager { * * @hide */ - public static int[] getInputDeviceIds() { + public int[] getInputDeviceIds() { try { - return sIm.getInputDeviceIds(); + return mIm.getInputDeviceIds(); } catch (RemoteException ex) { throw new RuntimeException("Could not get input device ids.", ex); } @@ -458,10 +382,10 @@ public final class InputManager { * * @hide */ - public static boolean[] deviceHasKeys(int[] keyCodes) { + public boolean[] deviceHasKeys(int[] keyCodes) { boolean[] ret = new boolean[keyCodes.length]; try { - sIm.hasKeys(-1, InputDevice.SOURCE_ANY, keyCodes, ret); + mIm.hasKeys(-1, InputDevice.SOURCE_ANY, keyCodes, ret); } catch (RemoteException e) { // no fallback; just return the empty array } @@ -489,7 +413,7 @@ public final class InputManager { * * @hide */ - public static boolean injectInputEvent(InputEvent event, int mode) { + public boolean injectInputEvent(InputEvent event, int mode) { if (event == null) { throw new IllegalArgumentException("event must not be null"); } @@ -500,152 +424,9 @@ public final class InputManager { } try { - return sIm.injectInputEvent(event, mode); + return mIm.injectInputEvent(event, mode); } catch (RemoteException ex) { return false; } } - - private static String makeKeyboardLayoutDescriptor(String packageName, - String receiverName, String keyboardName) { - return packageName + "/" + receiverName + "/" + keyboardName; - } - - private static KeyboardLayoutDescriptor parseKeyboardLayoutDescriptor(String descriptor) { - int pos = descriptor.indexOf('/'); - if (pos < 0 || pos + 1 == descriptor.length()) { - return null; - } - int pos2 = descriptor.indexOf('/', pos + 1); - if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) { - return null; - } - - KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor(); - result.packageName = descriptor.substring(0, pos); - result.receiverName = descriptor.substring(pos + 1, pos2); - result.keyboardLayoutName = descriptor.substring(pos2 + 1); - return result; - } - - /** - * Describes a keyboard layout. - * - * @hide - */ - public static final class KeyboardLayout implements Parcelable, - Comparable<KeyboardLayout> { - private final String mDescriptor; - private final String mLabel; - private final int mKeyCharacterMapResId; - - private KeyCharacterMap mKeyCharacterMap; - - public static final Parcelable.Creator<KeyboardLayout> CREATOR = - new Parcelable.Creator<KeyboardLayout>() { - public KeyboardLayout createFromParcel(Parcel source) { - return new KeyboardLayout(source); - } - public KeyboardLayout[] newArray(int size) { - return new KeyboardLayout[size]; - } - }; - - private KeyboardLayout(String descriptor, - String label, int keyCharacterMapResId) { - mDescriptor = descriptor; - mLabel = label; - mKeyCharacterMapResId = keyCharacterMapResId; - } - - private KeyboardLayout(Parcel source) { - mDescriptor = source.readString(); - mLabel = source.readString(); - mKeyCharacterMapResId = source.readInt(); - } - - /** - * Gets the keyboard layout descriptor, which can be used to retrieve - * the keyboard layout again later using - * {@link InputManager#getKeyboardLayout(String)}. - * - * @return The keyboard layout descriptor. - */ - public String getDescriptor() { - return mDescriptor; - } - - /** - * Gets the keyboard layout descriptive label to show in the user interface. - * @return The keyboard layout descriptive label. - */ - public String getLabel() { - return mLabel; - } - - /** - * Loads the key character map associated with the keyboard layout. - * - * @param pm The package manager. - * @return The key character map, or null if it could not be loaded for any reason. - */ - public KeyCharacterMap loadKeyCharacterMap(PackageManager pm) { - if (pm == null) { - throw new IllegalArgumentException("pm must not be null"); - } - - if (mKeyCharacterMap == null) { - KeyboardLayoutDescriptor d = parseKeyboardLayoutDescriptor(mDescriptor); - if (d == null) { - Log.e(TAG, "Could not load key character map '" + mDescriptor - + "' because the descriptor could not be parsed."); - return null; - } - - CharSequence cs = pm.getText(d.packageName, mKeyCharacterMapResId, null); - if (cs == null) { - Log.e(TAG, "Could not load key character map '" + mDescriptor - + "' because its associated resource could not be loaded."); - return null; - } - - try { - mKeyCharacterMap = KeyCharacterMap.load(cs); - } catch (UnavailableException ex) { - Log.e(TAG, "Could not load key character map '" + mDescriptor - + "' due to an error while parsing.", ex); - return null; - } - } - return mKeyCharacterMap; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mDescriptor); - dest.writeString(mLabel); - dest.writeInt(mKeyCharacterMapResId); - } - - @Override - public int compareTo(KeyboardLayout another) { - return mLabel.compareToIgnoreCase(another.mLabel); - } - - @Override - public String toString() { - return mLabel; - } - } - - private static final class KeyboardLayoutDescriptor { - public String packageName; - public String receiverName; - public String keyboardLayoutName; - } } diff --git a/core/java/android/hardware/input/KeyboardLayout.aidl b/core/java/android/hardware/input/KeyboardLayout.aidl new file mode 100644 index 0000000..226e384 --- /dev/null +++ b/core/java/android/hardware/input/KeyboardLayout.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.input; + +parcelable KeyboardLayout; diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java new file mode 100644 index 0000000..e75a6dc --- /dev/null +++ b/core/java/android/hardware/input/KeyboardLayout.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.input; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Describes a keyboard layout. + * + * @hide + */ +public final class KeyboardLayout implements Parcelable, + Comparable<KeyboardLayout> { + private final String mDescriptor; + private final String mLabel; + + public static final Parcelable.Creator<KeyboardLayout> CREATOR = + new Parcelable.Creator<KeyboardLayout>() { + public KeyboardLayout createFromParcel(Parcel source) { + return new KeyboardLayout(source); + } + public KeyboardLayout[] newArray(int size) { + return new KeyboardLayout[size]; + } + }; + + public KeyboardLayout(String descriptor, String label) { + mDescriptor = descriptor; + mLabel = label; + } + + private KeyboardLayout(Parcel source) { + mDescriptor = source.readString(); + mLabel = source.readString(); + } + + /** + * Gets the keyboard layout descriptor, which can be used to retrieve + * the keyboard layout again later using + * {@link InputManager#getKeyboardLayout(String)}. + * + * @return The keyboard layout descriptor. + */ + public String getDescriptor() { + return mDescriptor; + } + + /** + * Gets the keyboard layout descriptive label to show in the user interface. + * @return The keyboard layout descriptive label. + */ + public String getLabel() { + return mLabel; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mDescriptor); + dest.writeString(mLabel); + } + + @Override + public int compareTo(KeyboardLayout another) { + return mLabel.compareToIgnoreCase(another.mLabel); + } + + @Override + public String toString() { + return mLabel; + } +}
\ No newline at end of file diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index ba7dc4a..332f40a 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1712,8 +1712,8 @@ public class InputMethodService extends AbstractInputMethodService { /** * Override this to intercept key down events before they are processed by the - * application. If you return true, the application will not itself - * process the event. If you return true, the normal application processing + * application. If you return true, the application will not + * process the event itself. If you return false, the normal application processing * will occur as if the IME had not seen the event at all. * * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK diff --git a/core/java/android/net/NetworkQuotaInfo.java b/core/java/android/net/NetworkQuotaInfo.java index 6535256..1725ed7 100644 --- a/core/java/android/net/NetworkQuotaInfo.java +++ b/core/java/android/net/NetworkQuotaInfo.java @@ -57,12 +57,12 @@ public class NetworkQuotaInfo implements Parcelable { return mHardLimitBytes; } - /** {@inheritDoc} */ + @Override public int describeContents() { return 0; } - /** {@inheritDoc} */ + @Override public void writeToParcel(Parcel out, int flags) { out.writeLong(mEstimatedBytes); out.writeLong(mSoftLimitBytes); @@ -70,10 +70,12 @@ public class NetworkQuotaInfo implements Parcelable { } public static final Creator<NetworkQuotaInfo> CREATOR = new Creator<NetworkQuotaInfo>() { + @Override public NetworkQuotaInfo createFromParcel(Parcel in) { return new NetworkQuotaInfo(in); } + @Override public NetworkQuotaInfo[] newArray(int size) { return new NetworkQuotaInfo[size]; } diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java index 704111b..2fc69ad 100644 --- a/core/java/android/net/NetworkState.java +++ b/core/java/android/net/NetworkState.java @@ -52,12 +52,12 @@ public class NetworkState implements Parcelable { subscriberId = in.readString(); } - /** {@inheritDoc} */ + @Override public int describeContents() { return 0; } - /** {@inheritDoc} */ + @Override public void writeToParcel(Parcel out, int flags) { out.writeParcelable(networkInfo, flags); out.writeParcelable(linkProperties, flags); @@ -66,10 +66,12 @@ public class NetworkState implements Parcelable { } public static final Creator<NetworkState> CREATOR = new Creator<NetworkState>() { + @Override public NetworkState createFromParcel(Parcel in) { return new NetworkState(in); } + @Override public NetworkState[] newArray(int size) { return new NetworkState[size]; } diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 7a1ef66..844d055 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -155,7 +155,7 @@ public class NetworkStats implements Parcelable { operations = parcel.createLongArray(); } - /** {@inheritDoc} */ + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(elapsedRealtime); dest.writeInt(size); @@ -352,10 +352,9 @@ public class NetworkStats implements Parcelable { * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface}, * since operation counts are at data layer. */ - @Deprecated public void spliceOperationsFrom(NetworkStats stats) { for (int i = 0; i < size; i++) { - final int j = stats.findIndex(IFACE_ALL, uid[i], set[i], tag[i]); + final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i]); if (j == -1) { operations[i] = 0; } else { @@ -663,16 +662,18 @@ public class NetworkStats implements Parcelable { return writer.toString(); } - /** {@inheritDoc} */ + @Override public int describeContents() { return 0; } public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() { + @Override public NetworkStats createFromParcel(Parcel in) { return new NetworkStats(in); } + @Override public NetworkStats[] newArray(int size) { return new NetworkStats[size]; } diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index faf8a3f..0003c6e 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -130,7 +130,7 @@ public class NetworkStatsHistory implements Parcelable { totalBytes = in.readLong(); } - /** {@inheritDoc} */ + @Override public void writeToParcel(Parcel out, int flags) { out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); @@ -191,7 +191,7 @@ public class NetworkStatsHistory implements Parcelable { writeVarLongArray(out, operations, bucketCount); } - /** {@inheritDoc} */ + @Override public int describeContents() { return 0; } @@ -586,10 +586,12 @@ public class NetworkStatsHistory implements Parcelable { } public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() { + @Override public NetworkStatsHistory createFromParcel(Parcel in) { return new NetworkStatsHistory(in); } + @Override public NetworkStatsHistory[] newArray(int size) { return new NetworkStatsHistory[size]; } diff --git a/core/java/android/net/nsd/DnsSdServiceInfo.java b/core/java/android/net/nsd/DnsSdServiceInfo.java index 47d6ec6..33c3eb9 100644 --- a/core/java/android/net/nsd/DnsSdServiceInfo.java +++ b/core/java/android/net/nsd/DnsSdServiceInfo.java @@ -19,6 +19,8 @@ package android.net.nsd; import android.os.Parcelable; import android.os.Parcel; +import java.net.InetAddress; + /** * Defines a service based on DNS service discovery * {@hide} @@ -27,20 +29,20 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { private String mServiceName; - private String mRegistrationType; + private String mServiceType; private DnsSdTxtRecord mTxtRecord; - private String mHostname; + private InetAddress mHost; private int mPort; - DnsSdServiceInfo() { + public DnsSdServiceInfo() { } - DnsSdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) { + public DnsSdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) { mServiceName = sn; - mRegistrationType = rt; + mServiceType = rt; mTxtRecord = tr; } @@ -59,13 +61,13 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { @Override /** @hide */ public String getServiceType() { - return mRegistrationType; + return mServiceType; } @Override /** @hide */ public void setServiceType(String s) { - mRegistrationType = s; + mServiceType = s; } public DnsSdTxtRecord getTxtRecord() { @@ -76,12 +78,12 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { mTxtRecord = new DnsSdTxtRecord(t); } - public String getHostName() { - return mHostname; + public InetAddress getHost() { + return mHost; } - public void setHostName(String s) { - mHostname = s; + public void setHost(InetAddress s) { + mHost = s; } public int getPort() { @@ -96,7 +98,9 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { StringBuffer sb = new StringBuffer(); sb.append("name: ").append(mServiceName). - append("type: ").append(mRegistrationType). + append("type: ").append(mServiceType). + append("host: ").append(mHost). + append("port: ").append(mPort). append("txtRecord: ").append(mTxtRecord); return sb.toString(); } @@ -109,9 +113,14 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { /** Implement the Parcelable interface */ public void writeToParcel(Parcel dest, int flags) { dest.writeString(mServiceName); - dest.writeString(mRegistrationType); + dest.writeString(mServiceType); dest.writeParcelable(mTxtRecord, flags); - dest.writeString(mHostname); + if (mHost != null) { + dest.writeByte((byte)1); + dest.writeByteArray(mHost.getAddress()); + } else { + dest.writeByte((byte)0); + } dest.writeInt(mPort); } @@ -121,9 +130,15 @@ public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable { public DnsSdServiceInfo createFromParcel(Parcel in) { DnsSdServiceInfo info = new DnsSdServiceInfo(); info.mServiceName = in.readString(); - info.mRegistrationType = in.readString(); + info.mServiceType = in.readString(); info.mTxtRecord = in.readParcelable(null); - info.mHostname = in.readString(); + + if (in.readByte() == 1) { + try { + info.mHost = InetAddress.getByAddress(in.createByteArray()); + } catch (java.net.UnknownHostException e) {} + } + info.mPort = in.readInt(); return info; } diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index a109a98..505f11b 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -93,6 +93,15 @@ public class NsdManager { /** @hide */ public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 17; + /** @hide */ + public static final int STOP_RESOLVE = BASE + 18; + /** @hide */ + public static final int STOP_RESOLVE_FAILED = BASE + 19; + /** @hide */ + public static final int STOP_RESOLVE_SUCCEEDED = BASE + 20; + + + /** * Create a new Nsd instance. Applications use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve @@ -117,10 +126,23 @@ public class NsdManager { /** * Indicates that the operation failed because the framework is busy and - * unable to service the request + * unable to service the request. */ public static final int BUSY = 2; + /** + * Indicates that the operation failed because it is already active. + */ + public static final int ALREADY_ACTIVE = 3; + + /** + * Indicates that the operation failed because maximum limit on + * service registrations has reached. + */ + public static final int MAX_REGS_REACHED = 4; + + + /** Interface for callback invocation when framework channel is connected or lost */ public interface ChannelListener { public void onChannelConnected(Channel c); @@ -188,6 +210,7 @@ public class NsdManager { private DnsSdRegisterListener mDnsSdRegisterListener; private DnsSdUpdateRegistrationListener mDnsSdUpdateListener; private DnsSdResolveListener mDnsSdResolveListener; + private ActionListener mDnsSdStopResolveListener; AsyncChannel mAsyncChannel; ServiceHandler mHandler; @@ -278,6 +301,16 @@ public class NsdManager { (DnsSdServiceInfo) message.obj); } break; + case STOP_RESOLVE_FAILED: + if (mDnsSdStopResolveListener!= null) { + mDnsSdStopResolveListener.onFailure(message.arg1); + } + break; + case STOP_RESOLVE_SUCCEEDED: + if (mDnsSdStopResolveListener != null) { + mDnsSdStopResolveListener.onSuccess(); + } + break; default: Log.d(TAG, "Ignored " + message); break; @@ -345,6 +378,14 @@ public class NsdManager { c.mDnsSdResolveListener = b; } + /** + * Set the listener for stopping service resolution. Can be null. + */ + public void setStopResolveListener(Channel c, ActionListener b) { + if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + c.mDnsSdStopResolveListener = b; + } + public void registerService(Channel c, DnsSdServiceInfo serviceInfo) { if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); if (serviceInfo == null) throw new IllegalArgumentException("Null serviceInfo"); @@ -378,6 +419,13 @@ public class NsdManager { c.mAsyncChannel.sendMessage(RESOLVE_SERVICE, serviceInfo); } + public void stopServiceResolve(Channel c) { + if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + if (c.mDnsSdResolveListener == null) throw new + IllegalStateException("Resolve listener needs to be set first"); + c.mAsyncChannel.sendMessage(STOP_RESOLVE); + } + /** * Get a reference to NetworkService handler. This is used to establish * an AsyncChannel communication with the service diff --git a/core/java/android/provider/BrowserContract.java b/core/java/android/provider/BrowserContract.java index d678205..118b5eb 100644 --- a/core/java/android/provider/BrowserContract.java +++ b/core/java/android/provider/BrowserContract.java @@ -30,6 +30,15 @@ import android.os.RemoteException; import android.util.Pair; /** + * <p> + * The contract between the browser provider and applications. Contains the definition + * for the supported URIS and columns. + * </p> + * <h3>Overview</h3> + * <p> + * BrowserContract defines an database of browser-related information which are bookmarks, + * history, images and the mapping between the image and URL. + * </p> * @hide */ public class BrowserContract { @@ -45,12 +54,14 @@ public class BrowserContract { * the dirty flag is not automatically set and the "syncToNetwork" parameter * is set to false when calling * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)}. + * @hide */ public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter"; /** * A parameter for use when querying any table that allows specifying a limit on the number * of rows returned. + * @hide */ public static final String PARAM_LIMIT = "limit"; @@ -58,6 +69,8 @@ public class BrowserContract { * Generic columns for use by sync adapters. The specific functions of * these columns are private to the sync adapter. Other clients of the API * should not attempt to either read or write these columns. + * + * @hide */ interface BaseSyncColumns { /** Generic column for use by sync adapters. */ @@ -74,6 +87,7 @@ public class BrowserContract { /** * Convenience definitions for use in implementing chrome bookmarks sync in the Bookmarks table. + * @hide */ public static final class ChromeSyncColumns { private ChromeSyncColumns() {} @@ -93,6 +107,7 @@ public class BrowserContract { /** * Columns that appear when each row of a table belongs to a specific * account, including sync information that an account may need. + * @hide */ interface SyncColumns extends BaseSyncColumns { /** @@ -144,13 +159,14 @@ public class BrowserContract { public static final String _ID = "_id"; /** - * The URL of the bookmark. + * This column is valid when the row is a URL. The history table's URL + * can not be updated. * <P>Type: TEXT (URL)</P> */ public static final String URL = "url"; /** - * The user visible title of the bookmark. + * The user visible title. * <P>Type: TEXT</P> */ public static final String TITLE = "title"; @@ -159,10 +175,14 @@ public class BrowserContract { * The time that this row was created on its originating client (msecs * since the epoch). * <P>Type: INTEGER</P> + * @hide */ public static final String DATE_CREATED = "created"; } + /** + * @hide + */ interface ImageColumns { /** * The favicon of the bookmark, may be NULL. @@ -182,7 +202,6 @@ public class BrowserContract { * The touch icon for the web page, may be NULL. * Must decode via {@link BitmapFactory#decodeByteArray}. * <p>Type: BLOB (image)</p> - * @hide */ public static final String TOUCH_ICON = "touch_icon"; } @@ -200,9 +219,26 @@ public class BrowserContract { */ public static final String VISITS = "visits"; + /** + * @hide + */ public static final String USER_ENTERED = "user_entered"; } + interface ImageMappingColumns { + /** + * The ID of the image in Images. One image can map onto the multiple URLs. + * <P>Type: INTEGER (long)</P> + */ + public static final String IMAGE_ID = "image_id"; + + /** + * The URL. The URL can map onto the different type of images. + * <P>Type: TEXT (URL)</P> + */ + public static final String URL = "url"; + } + /** * The bookmarks table, which holds the user's browser bookmarks. */ @@ -218,24 +254,71 @@ public class BrowserContract { public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "bookmarks"); /** + * Used in {@link Bookmarks#TYPE} column and indicats the row is a bookmark. + */ + public static final int BOOKMARK_TYPE_BOOKMARK = 1; + + /** + * Used in {@link Bookmarks#TYPE} column and indicats the row is a folder. + */ + public static final int BOOKMARK_TYPE_FOLDER = 2; + + /** + * Used in {@link Bookmarks#TYPE} column and indicats the row is the bookmark bar folder. + */ + public static final int BOOKMARK_TYPE_BOOKMARK_BAR_FOLDER = 3; + + /** + * Used in {@link Bookmarks#TYPE} column and indicats the row is other folder and + */ + public static final int BOOKMARK_TYPE_OTHER_FOLDER = 4; + + /** + * Used in {@link Bookmarks#TYPE} column and indicats the row is other folder, . + */ + public static final int BOOKMARK_TYPE_MOBILE_FOLDER = 5; + + /** + * The type of the item. + * <P>Type: INTEGER</P> + * <p>Allowed values are:</p> + * <p> + * <ul> + * <li>{@link #BOOKMARK_TYPE_BOOKMARK}</li> + * <li>{@link #BOOKMARK_TYPE_FOLDER}</li> + * <li>{@link #BOOKMARK_TYPE_BOOKMARK_BAR_FOLDER}</li> + * <li>{@link #BOOKMARK_TYPE_OTHER_FOLDER}</li> + * <li>{@link #BOOKMARK_TYPE_MOBILE_FOLDER}</li> + * </ul> + * </p> + * <p> The TYPE_BOOKMARK_BAR_FOLDER, TYPE_OTHER_FOLDER and TYPE_MOBILE_FOLDER + * can not be updated or deleted.</p> + */ + public static final String TYPE = "type"; + + /** * The content:// style URI for the default folder + * @hide */ public static final Uri CONTENT_URI_DEFAULT_FOLDER = Uri.withAppendedPath(CONTENT_URI, "folder"); /** * Query parameter used to specify an account name + * @hide */ public static final String PARAM_ACCOUNT_NAME = "acct_name"; /** * Query parameter used to specify an account type + * @hide */ public static final String PARAM_ACCOUNT_TYPE = "acct_type"; /** * Builds a URI that points to a specific folder. * @param folderId the ID of the folder to point to + * @hide */ public static final Uri buildFolderUri(long folderId) { return ContentUris.withAppendedId(CONTENT_URI_DEFAULT_FOLDER, folderId); @@ -255,6 +338,7 @@ public class BrowserContract { * Query parameter to use if you want to see deleted bookmarks that are still * around on the device and haven't been synced yet. * @see #IS_DELETED + * @hide */ public static final String QUERY_PARAMETER_SHOW_DELETED = "show_deleted"; @@ -262,6 +346,7 @@ public class BrowserContract { * Flag indicating if an item is a folder or bookmark. Non-zero values indicate * a folder and zero indicates a bookmark. * <P>Type: INTEGER (boolean)</P> + * @hide */ public static final String IS_FOLDER = "folder"; @@ -274,6 +359,7 @@ public class BrowserContract { /** * The source ID for an item's parent. Read-only. * @see #PARENT + * @hide */ public static final String PARENT_SOURCE_ID = "parent_source"; @@ -281,6 +367,7 @@ public class BrowserContract { * The position of the bookmark in relation to it's siblings that share the same * {@link #PARENT}. May be negative. * <P>Type: INTEGER</P> + * @hide */ public static final String POSITION = "position"; @@ -288,6 +375,7 @@ public class BrowserContract { * The item that the bookmark should be inserted after. * May be negative. * <P>Type: INTEGER</P> + * @hide */ public static final String INSERT_AFTER = "insert_after"; @@ -296,6 +384,7 @@ public class BrowserContract { * May be negative. * <P>Type: INTEGER</P> * @see #INSERT_AFTER + * @hide */ public static final String INSERT_AFTER_SOURCE_ID = "insert_after_source"; @@ -305,12 +394,14 @@ public class BrowserContract { * to the URI when performing your query. * <p>Type: INTEGER (non-zero if the item has been deleted, zero if it hasn't) * @see #QUERY_PARAMETER_SHOW_DELETED + * @hide */ public static final String IS_DELETED = "deleted"; } /** * Read-only table that lists all the accounts that are used to provide bookmarks. + * @hide */ public static final class Accounts { /** @@ -410,6 +501,7 @@ public class BrowserContract { * A table provided for sync adapters to use for storing private sync state data. * * @see SyncStateContract + * @hide */ public static final class SyncState implements SyncStateContract.Columns { /** @@ -459,8 +551,18 @@ public class BrowserContract { } /** - * Stores images for URLs. Only support query() and update(). - * @hide + * <p> + * Stores images for URLs. + * </p> + * <p> + * The rows in this table can not be updated since there might have multiple URLs mapping onto + * the same image. If you want to update a URL's image, you need to add the new image in this + * table, then update the mapping onto the added image. + * </p> + * <p> + * Every image should be at least associated with one URL, otherwise it will be removed after a + * while. + * </p> */ public static final class Images implements ImageColumns { /** @@ -474,15 +576,93 @@ public class BrowserContract { public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "images"); /** + * The MIME type of {@link #CONTENT_URI} providing a directory of images. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/images"; + + /** + * The MIME type of a {@link #CONTENT_URI} of a single image. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/images"; + + /** + * Used in {@link Images#TYPE} column and indicats the row is a favicon. + */ + public static final int IMAGE_TYPE_FAVICON = 1; + + /** + * Used in {@link Images#TYPE} column and indicats the row is a precomposed touch icon. + */ + public static final int IMAGE_TYPE_PRECOMPOSED_TOUCH_ICON = 2; + + /** + * Used in {@link Images#TYPE} column and indicats the row is a touch icon. + */ + public static final int IMAGE_TYPE_TOUCH_ICON = 4; + + /** + * The type of item in the table. + * <P>Type: INTEGER</P> + * <p>Allowed values are:</p> + * <p> + * <ul> + * <li>{@link #IMAGE_TYPE_FAVICON}</li> + * <li>{@link #IMAGE_TYPE_PRECOMPOSED_TOUCH_ICON}</li> + * <li>{@link #IMAGE_TYPE_TOUCH_ICON}</li> + * </ul> + * </p> + */ + public static final String TYPE = "type"; + + /** + * The image data. + * <p>Type: BLOB (image)</p> + */ + public static final String DATA = "data"; + + /** * The URL the images came from. * <P>Type: TEXT (URL)</P> + * @hide */ public static final String URL = "url_key"; } /** + * <p> + * A table that stores the mappings between the image and the URL. + * </p> + * <p> + * Deleting or Updating a mapping might also deletes the mapped image if there is no other URL + * maps onto it. + * </p> + */ + public static final class ImageMappings implements ImageMappingColumns { + /** + * This utility class cannot be instantiated + */ + private ImageMappings() {} + + /** + * The content:// style URI for this table + */ + public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "image_mappings"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of image mappings. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image_mappings"; + + /** + * The MIME type of a {@link #CONTENT_URI} of a single image mapping. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/image_mappings"; + } + + /** * A combined view of bookmarks and history. All bookmarks in all folders are included and * no folders are included. + * @hide */ public static final class Combined implements CommonColumns, HistoryColumns, ImageColumns { /** @@ -505,6 +685,7 @@ public class BrowserContract { /** * A table that stores settings specific to the browser. Only support query and insert. + * @hide */ public static final class Settings { /** diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 0e9306b..e4729c7 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -7452,7 +7452,7 @@ public final class ContactsContract { /** * <p> * API allowing applications to send usage information for each {@link Data} row to the - * Contacts Provider. + * Contacts Provider. Applications can also clear all usage information. * </p> * <p> * With the feedback, Contacts Provider may return more contextually appropriate results for @@ -7497,6 +7497,12 @@ public final class ContactsContract { * boolean successful = resolver.update(uri, new ContentValues(), null, null) > 0; * </pre> * </p> + * <p> + * Applications can also clear all usage information with: + * <pre> + * boolean successful = resolver.delete(DataUsageFeedback.FEEDBACK_URI, null, null) > 0; + * </pre> + * </p> */ public static final class DataUsageFeedback { diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java new file mode 100644 index 0000000..83464c9 --- /dev/null +++ b/core/java/android/service/dreams/Dream.java @@ -0,0 +1,392 @@ +/** + * + */ +package android.service.dreams; + +import com.android.internal.policy.PolicyManager; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.graphics.drawable.ColorDrawable; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Slog; +import android.view.ActionMode; +import android.view.IWindowManager; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager.LayoutParams; +import android.view.accessibility.AccessibilityEvent; +import android.view.WindowManager; +import android.view.WindowManagerImpl; + +/** + * @hide + * + */ +public class Dream extends Service implements Window.Callback { + private final static boolean DEBUG = true; + private final static String TAG = "Dream"; + + /** + * The {@link Intent} that must be declared as handled by the service. + * To be supported, the service must also require the + * {@link android.Manifest.permission#BIND_WALLPAPER} permission so + * that other applications can not abuse it. + */ + @SdkConstant(SdkConstantType.SERVICE_ACTION) + public static final String SERVICE_INTERFACE = + "android.service.dreams.Dream"; + + private Window mWindow; + + private WindowManager mWindowManager; + private IDreamManager mSandman; + + private boolean mInteractive; + + final Handler mHandler = new Handler(); + + boolean mFinished = false; + + // begin Window.Callback methods + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (!mInteractive) { + finish(); + return true; + } + return mWindow.superDispatchKeyEvent(event); + } + + @Override + public boolean dispatchKeyShortcutEvent(KeyEvent event) { + if (!mInteractive) { + finish(); + return true; + } + return mWindow.superDispatchKeyShortcutEvent(event); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (!mInteractive) { + finish(); + return true; + } + return mWindow.superDispatchTouchEvent(event); + } + + @Override + public boolean dispatchTrackballEvent(MotionEvent event) { + if (!mInteractive) { + finish(); + return true; + } + return mWindow.superDispatchTrackballEvent(event); + } + + @Override + public boolean dispatchGenericMotionEvent(MotionEvent event) { + if (!mInteractive) { + finish(); + return true; + } + return mWindow.superDispatchGenericMotionEvent(event); + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + return false; + } + + @Override + public View onCreatePanelView(int featureId) { + return null; + } + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + return false; + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + return false; + } + + @Override + public boolean onMenuOpened(int featureId, Menu menu) { + return false; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + return false; + } + + @Override + public void onWindowAttributesChanged(LayoutParams attrs) { + + } + + @Override + public void onContentChanged() { + + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + + } + + @Override + public void onAttachedToWindow() { + mWindow.addFlags( + WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON + | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED + ); + lightsOut(); + } + + @Override + public void onDetachedFromWindow() { + } + + @Override + public void onPanelClosed(int featureId, Menu menu) { + } + + @Override + public boolean onSearchRequested() { + return false; + } + + @Override + public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) { + return null; + } + + @Override + public void onActionModeStarted(ActionMode mode) { + } + + @Override + public void onActionModeFinished(ActionMode mode) { + } + // end Window.Callback methods + + public WindowManager getWindowManager() { + return mWindowManager; + } + + public Window getWindow() { + return mWindow; + } + + /** + * Called when this Dream is constructed. Place your initialization here. + * + * Subclasses must call through to the superclass implementation. + */ + @Override + public void onCreate() { + super.onCreate(); + + if (DEBUG) Slog.v(TAG, "Dream created on thread " + Thread.currentThread().getId()); + + mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams")); + } + + /** + * Called when this Dream is started. Place your initialization here. + * + * Subclasses must call through to the superclass implementation. + * + * XXX(dsandler) Might want to make this final and have a different method for clients to override + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return super.onStartCommand(intent, flags, startId); + } + + /** + * Inflate a layout resource and set it to be the content view for this Dream. + * Behaves similarly to {@link android.app.Activity#setContentView(int)}. + * + * @param layoutResID Resource ID to be inflated. + * + * @see #setContentView(android.view.View) + * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + public void setContentView(int layoutResID) { + getWindow().setContentView(layoutResID); + } + + /** + * Set a view to be the content view for this Dream. + * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)}, + * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view. + * + * @param view The desired content to display. + * + * @see #setContentView(int) + * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) + */ + public void setContentView(View view) { + getWindow().setContentView(view); + } + + /** + * Set a view to be the content view for this Dream. + * Behaves similarly to + * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}. + * + * @param view The desired content to display. + * @param params Layout parameters for the view. + * + * @see #setContentView(android.view.View) + * @see #setContentView(int) + */ + public void setContentView(View view, ViewGroup.LayoutParams params) { + getWindow().setContentView(view, params); + } + + /** + * Add a view to the Dream's window, leaving other content views in place. + * + * @param view The desired content to display. + * @param params Layout parameters for the view. + */ + public void addContentView(View view, ViewGroup.LayoutParams params) { + getWindow().addContentView(view, params); + } + + /** + * @param mInteractive the mInteractive to set + */ + public void setInteractive(boolean mInteractive) { + this.mInteractive = mInteractive; + } + + /** + * @return the mInteractive + */ + public boolean isInteractive() { + return mInteractive; + } + + /** Convenience method for setting View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view. */ + protected void lightsOut() { + // turn the lights down low + final View v = mWindow.getDecorView(); + if (v != null) { + v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); + } + } + + /** + * Finds a view that was identified by the id attribute from the XML that + * was processed in {@link #onCreate}. + * + * @return The view if found or null otherwise. + */ + public View findViewById(int id) { + return getWindow().findViewById(id); + } + + /** + * Called when this Dream is being removed from the screen and stopped. + */ + @Override + public void onDestroy() { + super.onDestroy(); + mWindowManager.removeView(mWindow.getDecorView()); + } + + /** + * Creates a new dream window, attaches the current content view, and shows it. + * + * @param windowToken Binder to attach to the window to allow access to the correct window type. + * @hide + */ + final /*package*/ void attach(IBinder windowToken) { + if (DEBUG) Slog.v(TAG, "Dream attached on thread " + Thread.currentThread().getId()); + + mWindow = PolicyManager.makeNewWindow(this); + mWindow.setCallback(this); + mWindow.requestFeature(Window.FEATURE_NO_TITLE); + mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000)); + + if (DEBUG) Slog.v(TAG, "attaching window token: " + windowToken + + " to window of type " + WindowManager.LayoutParams.TYPE_DREAM); + + WindowManager.LayoutParams lp = mWindow.getAttributes(); + lp.type = WindowManager.LayoutParams.TYPE_DREAM; + lp.token = windowToken; + lp.windowAnimations = com.android.internal.R.style.Animation_Dream; + + //WindowManagerImpl.getDefault().addView(mWindow.getDecorView(), lp); + + if (DEBUG) Slog.v(TAG, "created and attached window: " + mWindow); + + mWindow.setWindowManager(null, windowToken, "dream", true); + mWindowManager = mWindow.getWindowManager(); + + // now make it visible + mHandler.post(new Runnable(){ + @Override + public void run() { + if (DEBUG) Slog.v(TAG, "Dream window added on thread " + Thread.currentThread().getId()); + + getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); + }}); + } + + /** + * Stop the dream and wake up. + * + * After this method is called, the service will be stopped. + */ + public void finish() { + if (mFinished) return; + try { + mSandman.awaken(); // assuming we were started by the DreamManager + stopSelf(); // if launched via any other means + mFinished = true; + } catch (RemoteException ex) { + // sigh + } + } + + class IDreamServiceWrapper extends IDreamService.Stub { + public IDreamServiceWrapper() { + } + + public void attach(IBinder windowToken) { + Dream.this.attach(windowToken); + } + } + + /** + * Implement to return the implementation of the internal accessibility + * service interface. Subclasses should not override. + */ + @Override + public final IBinder onBind(Intent intent) { + return new IDreamServiceWrapper(); + } +} diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java new file mode 100644 index 0000000..8712fa2 --- /dev/null +++ b/core/java/android/service/dreams/DreamManagerService.java @@ -0,0 +1,182 @@ +package android.service.dreams; + +import static android.provider.Settings.Secure.SCREENSAVER_COMPONENT; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +import com.android.internal.view.IInputMethod; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.provider.Settings; +import android.util.Log; +import android.util.Slog; +import android.view.IWindowManager; +import android.view.WindowManager; + +/** + * + * @hide + * + */ + +public class DreamManagerService + extends IDreamManager.Stub + implements ServiceConnection +{ + private static final boolean DEBUG = true; + private static final String TAG = "DreamManagerService"; + + final Object mLock = new Object[0]; + + private Context mContext; + private IWindowManager mIWindowManager; + + private ComponentName mCurrentDreamComponent; + private IDreamService mCurrentDream; + private Binder mCurrentDreamToken; + + public DreamManagerService(Context context) { + if (DEBUG) Slog.v(TAG, "DreamManagerService startup"); + mContext = context; + mIWindowManager = IWindowManager.Stub.asInterface( + ServiceManager.getService(Context.WINDOW_SERVICE)); + } + + private void checkPermission(String permission) { + if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) { + throw new SecurityException("Access denied to process: " + Binder.getCallingPid() + + ", must have permission " + permission); + } + } + + // IDreamManager method + public void dream() { + ComponentName name = getDreamComponent(); + if (name != null) { + synchronized (mLock) { + final long ident = Binder.clearCallingIdentity(); + try { + bindDreamComponentL(name, false); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + } + + // IDreamManager method + public void setDreamComponent(ComponentName name) { + Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString()); + } + + // IDreamManager method + public ComponentName getDreamComponent() { + // TODO(dsandler) don't load this every time, watch the value + String component = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENT); + if (component == null) { + component = mContext.getResources().getString( + com.android.internal.R.string.config_defaultDreamComponent); + } + if (component != null) { + return ComponentName.unflattenFromString(component); + } else { + return null; + } + } + + // IDreamManager method + public void testDream(ComponentName name) { + if (DEBUG) Slog.v(TAG, "startDream name=" + name + + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); +// checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT); + synchronized (mLock) { + final long ident = Binder.clearCallingIdentity(); + try { + bindDreamComponentL(name, true); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + // IDreamManager method + public void awaken() { + if (DEBUG) Slog.v(TAG, "awaken()"); + synchronized (mLock) { + if (mCurrentDream != null) { + mContext.unbindService(this); + } + } + } + + public void bindDreamComponentL(ComponentName componentName, boolean test) { + if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName + + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); + + Intent intent = new Intent(Intent.ACTION_MAIN) + .setComponent(componentName) + .addFlags( + Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS + ) + .putExtra("android.dreams.TEST", test); + + if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) { + Slog.w(TAG, "unable to bind service: " + componentName); + return; + } + mCurrentDreamComponent = componentName; + mCurrentDreamToken = new Binder(); + try { + if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurrentDreamToken + + " for window type: " + WindowManager.LayoutParams.TYPE_DREAM); + mIWindowManager.addWindowToken(mCurrentDreamToken, + WindowManager.LayoutParams.TYPE_DREAM); + } catch (RemoteException e) { + Slog.w(TAG, "Unable to add window token. Proceed at your own risk."); + } + + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + if (DEBUG) Slog.v(TAG, "connected to dream: " + name + " binder=" + service + " thread=" + Thread.currentThread().getId()); + + mCurrentDream = IDreamService.Stub.asInterface(service); + try { + if (DEBUG) Slog.v(TAG, "attaching with token:" + mCurrentDreamToken); + mCurrentDream.attach(mCurrentDreamToken); + } catch (RemoteException ex) { + Slog.w(TAG, "Unable to send window token to dream:" + ex); + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream); + mCurrentDream = null; + mCurrentDreamToken = null; + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("Dreamland:"); + pw.print(" component="); pw.println(mCurrentDreamComponent); + pw.print(" token="); pw.println(mCurrentDreamToken); + pw.print(" dream="); pw.println(mCurrentDream); + } + + public void systemReady() { + if (DEBUG) Slog.v(TAG, "ready to dream!"); + } + +} diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl new file mode 100644 index 0000000..7225013 --- /dev/null +++ b/core/java/android/service/dreams/IDreamManager.aidl @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2012, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.dreams; + +import android.os.Bundle; +import android.os.ParcelFileDescriptor; +import android.content.ComponentName; + +/** @hide */ +interface IDreamManager { + void dream(); + void awaken(); + void setDreamComponent(in ComponentName componentName); + ComponentName getDreamComponent(); + void testDream(in ComponentName componentName); +}
\ No newline at end of file diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl new file mode 100644 index 0000000..1bb241a --- /dev/null +++ b/core/java/android/service/dreams/IDreamService.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.dreams; + +/** + * @hide + */ +oneway interface IDreamService { + void attach(IBinder windowToken); +} diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java index f7a7eb8..11c169e 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -18,6 +18,7 @@ package android.text; import android.graphics.Canvas; import android.graphics.Paint; +import android.util.Log; import com.android.internal.util.ArrayUtils; @@ -50,6 +51,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable public SpannableStringBuilder(CharSequence text, int start, int end) { int srclen = end - start; + if (srclen < 0) throw new StringIndexOutOfBoundsException(); + int len = ArrayUtils.idealCharArraySize(srclen + 1); mText = new char[len]; mGapStart = srclen; @@ -72,7 +75,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (spans[i] instanceof NoCopySpan) { continue; } - + int st = sp.getSpanStart(spans[i]) - start; int en = sp.getSpanEnd(spans[i]) - start; int fl = sp.getSpanFlags(spans[i]); @@ -87,7 +90,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (en > end - start) en = end - start; - setSpan(spans[i], st, en, fl); + setSpan(false, spans[i], st, en, fl); } } } @@ -125,46 +128,38 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } private void resizeFor(int size) { - int newlen = ArrayUtils.idealCharArraySize(size + 1); - char[] newtext = new char[newlen]; + final int oldLength = mText.length; + final int newLength = ArrayUtils.idealCharArraySize(size + 1); + final int after = oldLength - (mGapStart + mGapLength); - int after = mText.length - (mGapStart + mGapLength); + char[] newText = new char[newLength]; + System.arraycopy(mText, 0, newText, 0, mGapStart); + System.arraycopy(mText, oldLength - after, newText, newLength - after, after); + mText = newText; - System.arraycopy(mText, 0, newtext, 0, mGapStart); - System.arraycopy(mText, mText.length - after, - newtext, newlen - after, after); + final int delta = newLength - oldLength; + mGapLength += delta; + if (mGapLength < 1) + new Exception("mGapLength < 1").printStackTrace(); for (int i = 0; i < mSpanCount; i++) { - if (mSpanStarts[i] > mGapStart) - mSpanStarts[i] += newlen - mText.length; - if (mSpanEnds[i] > mGapStart) - mSpanEnds[i] += newlen - mText.length; + if (mSpanStarts[i] > mGapStart) mSpanStarts[i] += delta; + if (mSpanEnds[i] > mGapStart) mSpanEnds[i] += delta; } - - int oldlen = mText.length; - mText = newtext; - mGapLength += mText.length - oldlen; - - if (mGapLength < 1) - new Exception("mGapLength < 1").printStackTrace(); } private void moveGapTo(int where) { if (where == mGapStart) return; - boolean atend = (where == length()); + boolean atEnd = (where == length()); if (where < mGapStart) { int overlap = mGapStart - where; - - System.arraycopy(mText, where, - mText, mGapStart + mGapLength - overlap, overlap); + System.arraycopy(mText, where, mText, mGapStart + mGapLength - overlap, overlap); } else /* where > mGapStart */ { int overlap = where - mGapStart; - - System.arraycopy(mText, where + mGapLength - overlap, - mText, mGapStart, overlap); + System.arraycopy(mText, where + mGapLength - overlap, mText, mGapStart, overlap); } // XXX be more clever @@ -179,7 +174,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable else if (start == where) { int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; - if (flag == POINT || (atend && flag == PARAGRAPH)) + if (flag == POINT || (atEnd && flag == PARAGRAPH)) start += mGapLength; } @@ -190,7 +185,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable else if (end == where) { int flag = (mSpanFlags[i] & END_MASK); - if (flag == POINT || (atend && flag == PARAGRAPH)) + if (flag == POINT || (atEnd && flag == PARAGRAPH)) end += mGapLength; } @@ -217,7 +212,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (mGapLength > 2 * length()) resizeFor(length()); - + return ret; // == this } @@ -225,7 +220,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable public void clear() { replace(0, length(), "", 0, 0); } - + // Documentation from interface public void clearSpans() { for (int i = mSpanCount - 1; i >= 0; i--) { @@ -262,45 +257,50 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable return append(String.valueOf(text)); } - private void change(int start, int end, CharSequence tb, int tbstart, int tbend) { - checkRange("replace", start, end); + private void change(int start, int end, CharSequence cs, int csStart, int csEnd) { + // Can be negative + final int nbNewChars = (csEnd - csStart) - (end - start); for (int i = mSpanCount - 1; i >= 0; i--) { - if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) { - int st = mSpanStarts[i]; - if (st > mGapStart) - st -= mGapLength; + int spanStart = mSpanStarts[i]; + if (spanStart > mGapStart) + spanStart -= mGapLength; - int en = mSpanEnds[i]; - if (en > mGapStart) - en -= mGapLength; + int spanEnd = mSpanEnds[i]; + if (spanEnd > mGapStart) + spanEnd -= mGapLength; - int ost = st; - int oen = en; + if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) { + int ost = spanStart; + int oen = spanEnd; int clen = length(); - if (st > start && st <= end) { - for (st = end; st < clen; st++) - if (st > end && charAt(st - 1) == '\n') + if (spanStart > start && spanStart <= end) { + for (spanStart = end; spanStart < clen; spanStart++) + if (spanStart > end && charAt(spanStart - 1) == '\n') break; } - if (en > start && en <= end) { - for (en = end; en < clen; en++) - if (en > end && charAt(en - 1) == '\n') + if (spanEnd > start && spanEnd <= end) { + for (spanEnd = end; spanEnd < clen; spanEnd++) + if (spanEnd > end && charAt(spanEnd - 1) == '\n') break; } - if (st != ost || en != oen) - setSpan(mSpans[i], st, en, mSpanFlags[i]); + if (spanStart != ost || spanEnd != oen) + setSpan(false, mSpans[i], spanStart, spanEnd, mSpanFlags[i]); } + + int flags = 0; + if (spanStart == start) flags |= SPAN_START_AT_START; + else if (spanStart == end + nbNewChars) flags |= SPAN_START_AT_END; + if (spanEnd == start) flags |= SPAN_END_AT_START; + else if (spanEnd == end + nbNewChars) flags |= SPAN_END_AT_END; + mSpanFlags[i] |= flags; } moveGapTo(end); - // Can be negative - final int nbNewChars = (tbend - tbstart) - (end - start); - if (nbNewChars >= mGapLength) { resizeFor(mText.length + nbNewChars - mGapLength); } @@ -311,47 +311,24 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (mGapLength < 1) new Exception("mGapLength < 1").printStackTrace(); - TextUtils.getChars(tb, tbstart, tbend, mText, start); - - if (tb instanceof Spanned) { - Spanned sp = (Spanned) tb; - Object[] spans = sp.getSpans(tbstart, tbend, Object.class); - - for (int i = 0; i < spans.length; i++) { - int st = sp.getSpanStart(spans[i]); - int en = sp.getSpanEnd(spans[i]); - - if (st < tbstart) - st = tbstart; - if (en > tbend) - en = tbend; - - if (getSpanStart(spans[i]) < 0) { - setSpan(false, spans[i], - st - tbstart + start, - en - tbstart + start, - sp.getSpanFlags(spans[i])); - } - } - } + TextUtils.getChars(cs, csStart, csEnd, mText, start); if (end > start) { // no need for span fixup on pure insertion boolean atEnd = (mGapStart + mGapLength == mText.length); for (int i = mSpanCount - 1; i >= 0; i--) { - if (mSpanStarts[i] >= start && - mSpanStarts[i] < mGapStart + mGapLength) { + if (mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength) { int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; - if (flag == POINT || (flag == PARAGRAPH && atEnd)) - mSpanStarts[i] = mGapStart + mGapLength; - else - mSpanStarts[i] = start; + if (flag == POINT || (flag == PARAGRAPH && atEnd)) { + mSpanStarts[i] = mGapStart + mGapLength; + } else { + mSpanStarts[i] = start; + } } - if (mSpanEnds[i] >= start && - mSpanEnds[i] < mGapStart + mGapLength) { + if (mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) { int flag = (mSpanFlags[i] & END_MASK); if (flag == POINT || (flag == PARAGRAPH && atEnd)) @@ -360,12 +337,34 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable mSpanEnds[i] = start; } - // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE + // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE, which are POINT_MARK and could + // get their boundaries swapped by the above code if (mSpanEnds[i] < mSpanStarts[i]) { removeSpan(i); } } } + + mSpanCountBeforeAdd = mSpanCount; + + if (cs instanceof Spanned) { + Spanned sp = (Spanned) cs; + Object[] spans = sp.getSpans(csStart, csEnd, Object.class); + + for (int i = 0; i < spans.length; i++) { + int st = sp.getSpanStart(spans[i]); + int en = sp.getSpanEnd(spans[i]); + + if (st < csStart) st = csStart; + if (en > csEnd) en = csEnd; + + // Add span only if this object is not yet used as a span in this string + if (getSpanStart(spans[i]) < 0 && !(spans[i] instanceof SpanWatcher)) { + setSpan(false, spans[i], st - csStart + start, en - csStart + start, + sp.getSpanFlags(spans[i])); + } + } + } } private void removeSpan(int i) { @@ -397,7 +396,9 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable // Documentation from interface public SpannableStringBuilder replace(final int start, final int end, - CharSequence tb, int tbstart, int tbend) { + CharSequence tb, int tbstart, int tbend) { + checkRange("replace", start, end); + int filtercount = mFilters.length; for (int i = 0; i < filtercount; i++) { CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end); @@ -412,81 +413,108 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable final int origLen = end - start; final int newLen = tbend - tbstart; - if (origLen == 0 && newLen == 0) { - return this; - } - TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class); sendBeforeTextChanged(textWatchers, start, origLen, newLen); - if (origLen == 0 || newLen == 0) { - change(start, end, tb, tbstart, tbend); - } else { - int selstart = Selection.getSelectionStart(this); - int selend = Selection.getSelectionEnd(this); - - // XXX just make the span fixups in change() do the right thing - // instead of this madness! - - checkRange("replace", start, end); - moveGapTo(end); - - if (mGapLength < 2) - resizeFor(length() + 1); - - for (int i = mSpanCount - 1; i >= 0; i--) { - if (mSpanStarts[i] == mGapStart) - mSpanStarts[i]++; - - if (mSpanEnds[i] == mGapStart) - mSpanEnds[i]++; - } + // Try to keep the cursor / selection at the same relative position during + // a text replacement. If replaced or replacement text length is zero, this + // is already taken care of. + boolean adjustSelection = origLen != 0 && newLen != 0; + int selectionStart = 0; + int selectionEnd = 0; + if (adjustSelection) { + selectionStart = Selection.getSelectionStart(this); + selectionEnd = Selection.getSelectionEnd(this); + } - mText[mGapStart] = ' '; - mGapStart++; - mGapLength--; + change(start, end, tb, tbstart, tbend); - if (mGapLength < 1) { - new Exception("mGapLength < 1").printStackTrace(); - } + if (adjustSelection) { + if (selectionStart > start && selectionStart < end) { + final int offset = (selectionStart - start) * newLen / origLen; + selectionStart = start + offset; - change(start + 1, start + 1, tb, tbstart, tbend); - change(start, start + 1, "", 0, 0); - change(start + newLen, start + newLen + origLen, "", 0, 0); - - /* - * Special case to keep the cursor in the same position - * if it was somewhere in the middle of the replaced region. - * If it was at the start or the end or crossing the whole - * replacement, it should already be where it belongs. - * TODO: Is there some more general mechanism that could - * accomplish this? - */ - if (selstart > start && selstart < end) { - long off = selstart - start; - - off = off * newLen / (end - start); - selstart = (int) off + start; - - setSpan(false, Selection.SELECTION_START, selstart, selstart, + setSpan(false, Selection.SELECTION_START, selectionStart, selectionStart, Spanned.SPAN_POINT_POINT); } - if (selend > start && selend < end) { - long off = selend - start; + if (selectionEnd > start && selectionEnd < end) { + final int offset = (selectionEnd - start) * newLen / origLen; + selectionEnd = start + offset; - off = off * newLen / (end - start); - selend = (int) off + start; - - setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT); + setSpan(false, Selection.SELECTION_END, selectionEnd, selectionEnd, + Spanned.SPAN_POINT_POINT); } } sendTextChanged(textWatchers, start, origLen, newLen); sendAfterTextChanged(textWatchers); + // Span watchers need to be called after text watchers, which may update the layout + sendToSpanWatchers(start, end, newLen - origLen); + return this; } + private void sendToSpanWatchers(int replaceStart, int replaceEnd, int nbNewChars) { + for (int i = 0; i < mSpanCountBeforeAdd; i++) { + int spanStart = mSpanStarts[i]; + int spanEnd = mSpanEnds[i]; + if (spanStart > mGapStart) spanStart -= mGapLength; + if (spanEnd > mGapStart) spanEnd -= mGapLength; + int spanFlags = mSpanFlags[i]; + + int newReplaceEnd = replaceEnd + nbNewChars; + boolean spanChanged = false; + int previousSpanStart = spanStart; + if (spanStart > newReplaceEnd) { + if (nbNewChars != 0) { + previousSpanStart -= nbNewChars; + spanChanged = true; + } + } else if (spanStart >= replaceStart) { + // No change if span start was already at replace interval boundaries before replace + if ((spanStart != replaceStart || + ((spanFlags & SPAN_START_AT_START) != SPAN_START_AT_START)) && + (spanStart != newReplaceEnd || + ((spanFlags & SPAN_START_AT_END) != SPAN_START_AT_END))) { + // TODO previousSpanStart is incorrect, but we would need to save all the + // previous spans' positions before replace to provide it + spanChanged = true; + } + } + int previousSpanEnd = spanEnd; + if (spanEnd > newReplaceEnd) { + if (nbNewChars != 0) { + previousSpanEnd -= nbNewChars; + spanChanged = true; + } + } else if (spanEnd >= replaceStart) { + // No change if span start was already at replace interval boundaries before replace + if ((spanEnd != replaceStart || + ((spanFlags & SPAN_END_AT_START) != SPAN_END_AT_START)) && + (spanEnd != newReplaceEnd || + ((spanFlags & SPAN_END_AT_END) != SPAN_END_AT_END))) { + // TODO same as above for previousSpanEnd + spanChanged = true; + } + } + + if (spanChanged) { + sendSpanChanged(mSpans[i], previousSpanStart, previousSpanEnd, spanStart, spanEnd); + } + mSpanFlags[i] &= ~SPAN_START_END_MASK; + } + + // The spans starting at mIntermediateSpanCount were added from the replacement text + for (int i = mSpanCountBeforeAdd; i < mSpanCount; i++) { + int spanStart = mSpanStarts[i]; + int spanEnd = mSpanEnds[i]; + if (spanStart > mGapStart) spanStart -= mGapLength; + if (spanEnd > mGapStart) spanEnd -= mGapLength; + sendSpanAdded(mSpans[i], spanStart, spanEnd); + } + } + /** * Mark the specified range of text with the specified object. * The flags determine how the span will behave when text is @@ -497,12 +525,10 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } private void setSpan(boolean send, Object what, int start, int end, int flags) { - int nstart = start; - int nend = end; - checkRange("setSpan", start, end); - if ((flags & START_MASK) == (PARAGRAPH << START_SHIFT)) { + int flagsStart = (flags & START_MASK) >> START_SHIFT; + if (flagsStart == PARAGRAPH) { if (start != 0 && start != length()) { char c = charAt(start - 1); @@ -511,7 +537,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } - if ((flags & END_MASK) == PARAGRAPH) { + int flagsEnd = flags & END_MASK; + if (flagsEnd == PARAGRAPH) { if (end != 0 && end != length()) { char c = charAt(end - 1); @@ -520,21 +547,30 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } + // 0-length Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + if (flagsStart == POINT && flagsEnd == MARK && start == end) { + if (send) Log.e("SpannableStringBuilder", + "SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length"); + // Silently ignore invalid spans when they are created from this class. + // This avoids the duplication of the above test code before all the + // calls to setSpan that are done in this class + return; + } + + int nstart = start; + int nend = end; + if (start > mGapStart) { start += mGapLength; } else if (start == mGapStart) { - int flag = (flags & START_MASK) >> START_SHIFT; - - if (flag == POINT || (flag == PARAGRAPH && start == length())) + if (flagsStart == POINT || (flagsStart == PARAGRAPH && start == length())) start += mGapLength; } if (end > mGapStart) { end += mGapLength; } else if (end == mGapStart) { - int flag = (flags & END_MASK); - - if (flag == POINT || (flag == PARAGRAPH && end == length())) + if (flagsEnd == POINT || (flagsEnd == PARAGRAPH && end == length())) end += mGapLength; } @@ -815,13 +851,12 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (end <= mGapStart) { System.arraycopy(mText, start, dest, destoff, end - start); } else if (start >= mGapStart) { - System.arraycopy(mText, start + mGapLength, - dest, destoff, end - start); + System.arraycopy(mText, start + mGapLength, dest, destoff, end - start); } else { System.arraycopy(mText, start, dest, destoff, mGapStart - start); System.arraycopy(mText, mGapStart + mGapLength, - dest, destoff + (mGapStart - start), - end - mGapStart); + dest, destoff + (mGapStart - start), + end - mGapStart); } } @@ -890,12 +925,14 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } - private void sendSpanChanged(Object what, int s, int e, int st, int en) { - SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en), SpanWatcher.class); - int n = recip.length; - + private void sendSpanChanged(Object what, int oldStart, int oldEnd, int start, int end) { + // The bounds of a possible SpanWatcher are guaranteed to be set before this method is + // called, so that the order of the span does not affect this broadcast. + SpanWatcher[] spanWatchers = getSpans(Math.min(oldStart, start), + Math.min(Math.max(oldEnd, end), length()), SpanWatcher.class); + int n = spanWatchers.length; for (int i = 0; i < n; i++) { - recip[i].onSpanChanged(this, what, s, e, st, en); + spanWatchers[i].onSpanChanged(this, what, oldStart, oldEnd, start, end); } } @@ -906,26 +943,23 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable private void checkRange(final String operation, int start, int end) { if (end < start) { throw new IndexOutOfBoundsException(operation + " " + - region(start, end) + - " has end before start"); + region(start, end) + " has end before start"); } int len = length(); if (start > len || end > len) { throw new IndexOutOfBoundsException(operation + " " + - region(start, end) + - " ends beyond length " + len); + region(start, end) + " ends beyond length " + len); } if (start < 0 || end < 0) { throw new IndexOutOfBoundsException(operation + " " + - region(start, end) + - " starts before 0"); + region(start, end) + " starts before 0"); } } -/* + /* private boolean isprint(char c) { // XXX if (c >= ' ' && c <= '~') return true; @@ -1004,7 +1038,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable System.out.print("\n"); } -*/ + */ /** * Don't call this yourself -- exists for Canvas to use internally. @@ -1050,7 +1084,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable } } - /** + /** * Don't call this yourself -- exists for Paint to use internally. * {@hide} */ @@ -1086,8 +1120,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable if (end <= mGapStart) { ret = p.getTextWidths(mText, start, end - start, widths); } else if (start >= mGapStart) { - ret = p.getTextWidths(mText, start + mGapLength, end - start, - widths); + ret = p.getTextWidths(mText, start + mGapLength, end - start, widths); } else { char[] buf = TextUtils.obtain(end - start); @@ -1232,12 +1265,21 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable private int[] mSpanEnds; private int[] mSpanFlags; private int mSpanCount; + private int mSpanCountBeforeAdd; // TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned} + private static final int MARK = 1; private static final int POINT = 2; private static final int PARAGRAPH = 3; private static final int START_MASK = 0xF0; private static final int END_MASK = 0x0F; private static final int START_SHIFT = 4; + + // These bits are not (currently) used by SPANNED flags + private static final int SPAN_START_AT_START = 0x1000; + private static final int SPAN_START_AT_END = 0x2000; + private static final int SPAN_END_AT_START = 0x4000; + private static final int SPAN_END_AT_END = 0x8000; + private static final int SPAN_START_END_MASK = 0xF000; } diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index b0399fd..8bc36b7 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -237,6 +237,17 @@ public abstract class HardwareRenderer { abstract boolean validate(); /** + * This method ensures the hardware renderer is in a valid state + * before executing the specified action. + * + * This method will attempt to set a valid state even if the window + * the renderer is attached to was destroyed. + * + * @return true if the action was run + */ + abstract boolean safelyRun(Runnable action); + + /** * Setup the hardware renderer for drawing. This is called whenever the * size of the target surface changes or when the surface is first created. * @@ -1380,20 +1391,39 @@ public abstract class HardwareRenderer { } @Override - void destroyHardwareResources(View view) { - if (view != null) { - boolean needsContext = true; - if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false; + boolean safelyRun(Runnable action) { + boolean needsContext = true; + if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false; + + if (needsContext) { + Gl20RendererEglContext managedContext = + (Gl20RendererEglContext) sEglContextStorage.get(); + if (managedContext == null) return false; + usePbufferSurface(managedContext.getContext()); + } + try { + action.run(); + } finally { if (needsContext) { - Gl20RendererEglContext managedContext = - (Gl20RendererEglContext) sEglContextStorage.get(); - if (managedContext == null) return; - usePbufferSurface(managedContext.getContext()); + sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); } + } - destroyResources(view); - GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); + return true; + } + + @Override + void destroyHardwareResources(final View view) { + if (view != null) { + safelyRun(new Runnable() { + @Override + public void run() { + destroyResources(view); + GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); + } + }); } } @@ -1434,6 +1464,9 @@ public abstract class HardwareRenderer { } else if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE); } + + sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); } private static void usePbufferSurface(EGLContext eglContext) { diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 6f8d09b..75b2c746 100755 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -39,13 +39,12 @@ import java.util.List; * </p> */ public final class InputDevice implements Parcelable { - private int mId; - private String mName; - private String mDescriptor; - private int mSources; - private int mKeyboardType; - private String mKeyCharacterMapFile; - + private final int mId; + private final String mName; + private final String mDescriptor; + private final int mSources; + private final int mKeyboardType; + private final KeyCharacterMap mKeyCharacterMap; private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>(); /** @@ -292,8 +291,43 @@ public final class InputDevice implements Parcelable { */ public static final int KEYBOARD_TYPE_ALPHABETIC = 2; + public static final Parcelable.Creator<InputDevice> CREATOR = + new Parcelable.Creator<InputDevice>() { + public InputDevice createFromParcel(Parcel in) { + return new InputDevice(in); + } + public InputDevice[] newArray(int size) { + return new InputDevice[size]; + } + }; + // Called by native code. - private InputDevice() { + private InputDevice(int id, String name, String descriptor, int sources, + int keyboardType, KeyCharacterMap keyCharacterMap) { + mId = id; + mName = name; + mDescriptor = descriptor; + mSources = sources; + mKeyboardType = keyboardType; + mKeyCharacterMap = keyCharacterMap; + } + + private InputDevice(Parcel in) { + mId = in.readInt(); + mName = in.readString(); + mDescriptor = in.readString(); + mSources = in.readInt(); + mKeyboardType = in.readInt(); + mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in); + + for (;;) { + int axis = in.readInt(); + if (axis < 0) { + break; + } + addMotionRange(axis, in.readInt(), + in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); + } } /** @@ -302,7 +336,7 @@ public final class InputDevice implements Parcelable { * @return The input device or null if not found. */ public static InputDevice getDevice(int id) { - return InputManager.getInputDevice(id); + return InputManager.getInstance().getInputDevice(id); } /** @@ -310,7 +344,7 @@ public final class InputDevice implements Parcelable { * @return The input device ids. */ public static int[] getDeviceIds() { - return InputManager.getInputDeviceIds(); + return InputManager.getInstance().getInputDeviceIds(); } /** @@ -356,6 +390,22 @@ public final class InputDevice implements Parcelable { } /** + * Returns true if the device is a virtual input device rather than a real one, + * such as the virtual keyboard (see {@link KeyCharacterMap#VIRTUAL_KEYBOARD}). + * <p> + * Virtual input devices are provided to implement system-level functionality + * and should not be seen or configured by users. + * </p> + * + * @return True if the device is virtual. + * + * @see KeyCharacterMap#VIRTUAL_KEYBOARD + */ + public boolean isVirtual() { + return mId < 0; + } + + /** * Gets the name of this input device. * @return The input device name. */ @@ -384,11 +434,7 @@ public final class InputDevice implements Parcelable { * @return The key character map. */ public KeyCharacterMap getKeyCharacterMap() { - return KeyCharacterMap.load(mId); - } - - String getKeyCharacterMapFile() { - return mKeyCharacterMapFile; + return mKeyCharacterMap; } /** @@ -453,6 +499,7 @@ public final class InputDevice implements Parcelable { return mMotionRanges; } + // Called from native code. private void addMotionRange(int axis, int source, float min, float max, float flat, float fuzz) { mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz)); @@ -545,37 +592,6 @@ public final class InputDevice implements Parcelable { } } - public static final Parcelable.Creator<InputDevice> CREATOR - = new Parcelable.Creator<InputDevice>() { - public InputDevice createFromParcel(Parcel in) { - InputDevice result = new InputDevice(); - result.readFromParcel(in); - return result; - } - - public InputDevice[] newArray(int size) { - return new InputDevice[size]; - } - }; - - private void readFromParcel(Parcel in) { - mId = in.readInt(); - mName = in.readString(); - mDescriptor = in.readString(); - mSources = in.readInt(); - mKeyboardType = in.readInt(); - mKeyCharacterMapFile = in.readString(); - - for (;;) { - int axis = in.readInt(); - if (axis < 0) { - break; - } - addMotionRange(axis, in.readInt(), - in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); - } - } - @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mId); @@ -583,7 +599,7 @@ public final class InputDevice implements Parcelable { out.writeString(mDescriptor); out.writeInt(mSources); out.writeInt(mKeyboardType); - out.writeString(mKeyCharacterMapFile); + mKeyCharacterMap.writeToParcel(out, flags); final int numRanges = mMotionRanges.size(); for (int i = 0; i < numRanges; i++) { @@ -623,8 +639,6 @@ public final class InputDevice implements Parcelable { } description.append("\n"); - description.append(" Key Character Map: ").append(mKeyCharacterMapFile).append("\n"); - description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" ("); appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java index b03f086..3d165ea 100644 --- a/core/java/android/view/KeyCharacterMap.java +++ b/core/java/android/view/KeyCharacterMap.java @@ -16,18 +16,21 @@ package android.view; +import android.os.Parcel; +import android.os.Parcelable; import android.text.method.MetaKeyKeyListener; import android.util.AndroidRuntimeException; import android.util.SparseIntArray; import android.hardware.input.InputManager; import android.util.SparseArray; +import android.view.InputDevice.MotionRange; import java.lang.Character; /** * Describes the keys provided by a keyboard device and their associated labels. */ -public class KeyCharacterMap { +public class KeyCharacterMap implements Parcelable { /** * The id of the device's primary built in keyboard is always 0. * @@ -134,12 +137,20 @@ public class KeyCharacterMap { */ public static final int MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED = 1; - private static SparseArray<KeyCharacterMap> sInstances = new SparseArray<KeyCharacterMap>(); + public static final Parcelable.Creator<KeyCharacterMap> CREATOR = + new Parcelable.Creator<KeyCharacterMap>() { + public KeyCharacterMap createFromParcel(Parcel in) { + return new KeyCharacterMap(in); + } + public KeyCharacterMap[] newArray(int size) { + return new KeyCharacterMap[size]; + } + }; - private final int mDeviceId; private int mPtr; - private static native int nativeLoad(String file); + private static native int nativeReadFromParcel(Parcel in); + private static native void nativeWriteToParcel(int ptr, Parcel out); private static native void nativeDispose(int ptr); private static native char nativeGetCharacter(int ptr, int keyCode, int metaState); @@ -149,10 +160,20 @@ public class KeyCharacterMap { private static native char nativeGetMatch(int ptr, int keyCode, char[] chars, int metaState); private static native char nativeGetDisplayLabel(int ptr, int keyCode); private static native int nativeGetKeyboardType(int ptr); - private static native KeyEvent[] nativeGetEvents(int ptr, int deviceId, char[] chars); + private static native KeyEvent[] nativeGetEvents(int ptr, char[] chars); + + private KeyCharacterMap(Parcel in) { + if (in == null) { + throw new IllegalArgumentException("parcel must not be null"); + } + mPtr = nativeReadFromParcel(in); + if (mPtr == 0) { + throw new RuntimeException("Could not read KeyCharacterMap from parcel."); + } + } - private KeyCharacterMap(int deviceId, int ptr) { - mDeviceId = deviceId; + // Called from native + private KeyCharacterMap(int ptr) { mPtr = ptr; } @@ -174,33 +195,16 @@ public class KeyCharacterMap { * is missing from the system. */ public static KeyCharacterMap load(int deviceId) { - synchronized (sInstances) { - KeyCharacterMap map = sInstances.get(deviceId); - if (map == null) { - String kcm = null; - if (deviceId != VIRTUAL_KEYBOARD) { - InputDevice device = InputDevice.getDevice(deviceId); - if (device != null) { - kcm = device.getKeyCharacterMapFile(); - } - } - if (kcm == null || kcm.length() == 0) { - kcm = "/system/usr/keychars/Virtual.kcm"; - } - int ptr = nativeLoad(kcm); // might throw - map = new KeyCharacterMap(deviceId, ptr); - sInstances.put(deviceId, map); + final InputManager im = InputManager.getInstance(); + InputDevice inputDevice = im.getInputDevice(deviceId); + if (inputDevice == null) { + inputDevice = im.getInputDevice(VIRTUAL_KEYBOARD); + if (inputDevice == null) { + throw new UnavailableException( + "Could not load key character map for device " + deviceId); } - return map; } - } - - /** - * TODO implement this - * @hide - */ - public static KeyCharacterMap load(CharSequence contents) { - return null; + return inputDevice.getKeyCharacterMap(); } /** @@ -437,7 +441,7 @@ public class KeyCharacterMap { if (chars == null) { throw new IllegalArgumentException("chars must not be null."); } - return nativeGetEvents(mPtr, mDeviceId, chars); + return nativeGetEvents(mPtr, chars); } /** @@ -527,7 +531,7 @@ public class KeyCharacterMap { * @return True if at least one attached keyboard supports the specified key code. */ public static boolean deviceHasKey(int keyCode) { - return InputManager.deviceHasKeys(new int[] { keyCode })[0]; + return InputManager.getInstance().deviceHasKeys(new int[] { keyCode })[0]; } /** @@ -541,7 +545,20 @@ public class KeyCharacterMap { * at the same index in the key codes array. */ public static boolean[] deviceHasKeys(int[] keyCodes) { - return InputManager.deviceHasKeys(keyCodes); + return InputManager.getInstance().deviceHasKeys(keyCodes); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + if (out == null) { + throw new IllegalArgumentException("parcel must not be null"); + } + nativeWriteToParcel(mPtr, out); + } + + @Override + public int describeContents() { + return 0; } /** diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 77fd8d2..e51ba3d 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -2715,6 +2715,67 @@ public final class MotionEvent extends InputEvent implements Parcelable { } /** + * Adds all of the movement samples of the specified event to this one if + * it is compatible. To be compatible, the event must have the same device id, + * source, action, flags, pointer count, pointer properties. + * + * Only applies to {@link #ACTION_MOVE} or {@link #ACTION_HOVER_MOVE} events. + * + * @param event The event whose movements samples should be added to this one + * if possible. + * @return True if batching was performed or false if batching was not possible. + * @hide + */ + public final boolean addBatch(MotionEvent event) { + final int action = nativeGetAction(mNativePtr); + if (action != ACTION_MOVE && action != ACTION_HOVER_MOVE) { + return false; + } + if (action != nativeGetAction(event.mNativePtr)) { + return false; + } + + if (nativeGetDeviceId(mNativePtr) != nativeGetDeviceId(event.mNativePtr) + || nativeGetSource(mNativePtr) != nativeGetSource(event.mNativePtr) + || nativeGetFlags(mNativePtr) != nativeGetFlags(event.mNativePtr)) { + return false; + } + + final int pointerCount = nativeGetPointerCount(mNativePtr); + if (pointerCount != nativeGetPointerCount(event.mNativePtr)) { + return false; + } + + synchronized (gSharedTempLock) { + ensureSharedTempPointerCapacity(Math.max(pointerCount, 2)); + final PointerProperties[] pp = gSharedTempPointerProperties; + final PointerCoords[] pc = gSharedTempPointerCoords; + + for (int i = 0; i < pointerCount; i++) { + nativeGetPointerProperties(mNativePtr, i, pp[0]); + nativeGetPointerProperties(event.mNativePtr, i, pp[1]); + if (!pp[0].equals(pp[1])) { + return false; + } + } + + final int metaState = nativeGetMetaState(event.mNativePtr); + final int historySize = nativeGetHistorySize(event.mNativePtr); + for (int h = 0; h <= historySize; h++) { + final int historyPos = (h == historySize ? HISTORY_CURRENT : h); + + for (int i = 0; i < pointerCount; i++) { + nativeGetPointerCoords(event.mNativePtr, i, historyPos, pc[i]); + } + + final long eventTimeNanos = nativeGetEventTimeNanos(event.mNativePtr, historyPos); + nativeAddBatch(mNativePtr, eventTimeNanos, pc, metaState); + } + } + return true; + } + + /** * Returns true if all points in the motion event are completely within the specified bounds. * @hide */ @@ -3416,5 +3477,22 @@ public final class MotionEvent extends InputEvent implements Parcelable { id = other.id; toolType = other.toolType; } + + @Override + public boolean equals(Object other) { + if (other instanceof PointerProperties) { + return equals((PointerProperties)other); + } + return false; + } + + private boolean equals(PointerProperties other) { + return other != null && id == other.id && toolType == other.toolType; + } + + @Override + public int hashCode() { + return id | (toolType << 8); + } } } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 3cd8b71..32029ba 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -187,7 +187,9 @@ public class TextureView extends View { public void setOpaque(boolean opaque) { if (opaque != mOpaque) { mOpaque = opaque; - updateLayer(); + if (mLayer != null) { + updateLayer(); + } } } @@ -204,7 +206,18 @@ public class TextureView extends View { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - destroySurface(); + if (mLayer != null && mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) { + boolean success = mAttachInfo.mHardwareRenderer.safelyRun(new Runnable() { + @Override + public void run() { + destroySurface(); + } + }); + + if (!success) { + Log.w(LOG_TAG, "TextureView was not able to destroy its surface: " + this); + } + } } private void destroySurface() { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index d62e32f..1fa19d1 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -4483,10 +4483,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal getDrawingRect(bounds); info.setBoundsInParent(bounds); - int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation; - getLocationOnScreen(locationOnScreen); - bounds.offsetTo(0, 0); - bounds.offset(locationOnScreen[0], locationOnScreen[1]); + getGlobalVisibleRect(bounds); + bounds.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop); info.setBoundsInScreen(bounds); if ((mPrivateFlags & IS_ROOT_NAMESPACE) == 0) { @@ -8698,7 +8696,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal invalidateParentCaches(); onScrollChanged(mScrollX, mScrollY, oldX, oldY); if (!awakenScrollBars()) { - invalidate(true); + postInvalidateOnAnimation(); } } } @@ -8852,7 +8850,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (invalidate) { // Invalidate to show the scrollbars - invalidate(true); + postInvalidateOnAnimation(); } if (scrollCache.state == ScrollabilityCache.OFF) { @@ -9212,6 +9210,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. + * + * @see #postDelayed + * @see #removeCallbacks */ public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; @@ -9241,6 +9242,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * result of true does not mean the Runnable will be processed -- * if the looper is quit before the delivery time of the message * occurs then the message will be dropped. + * + * @see #post + * @see #removeCallbacks */ public boolean postDelayed(Runnable action, long delayMillis) { final AttachInfo attachInfo = mAttachInfo; @@ -9261,7 +9265,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * * @param action The Runnable that will be executed. * - * @hide + * @see #postOnAnimationDelayed + * @see #removeCallbacks */ public void postOnAnimation(Runnable action) { final AttachInfo attachInfo = mAttachInfo; @@ -9286,7 +9291,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * @param delayMillis The delay (in milliseconds) until the Runnable * will be executed. * - * @hide + * @see #postOnAnimation + * @see #removeCallbacks */ public void postOnAnimationDelayed(Runnable action, long delayMillis) { final AttachInfo attachInfo = mAttachInfo; @@ -9311,6 +9317,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * false otherwise. When the returned value is true, the Runnable * may or may not have been actually removed from the message queue * (for instance, if the Runnable was not in the queue already.) + * + * @see #post + * @see #postDelayed + * @see #postOnAnimation + * @see #postOnAnimationDelayed */ public boolean removeCallbacks(Runnable action) { if (action != null) { @@ -9335,6 +9346,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * only when this View is attached to a window.</p> * * @see #invalidate() + * @see #postInvalidateDelayed(long) */ public void postInvalidate() { postInvalidateDelayed(0); @@ -9354,6 +9366,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * * @see #invalidate(int, int, int, int) * @see #invalidate(Rect) + * @see #postInvalidateDelayed(long, int, int, int, int) */ public void postInvalidate(int left, int top, int right, int bottom) { postInvalidateDelayed(0, left, top, right, bottom); @@ -9368,6 +9381,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * * @param delayMilliseconds the duration in milliseconds to delay the * invalidation by + * + * @see #invalidate() + * @see #postInvalidate() */ public void postInvalidateDelayed(long delayMilliseconds) { // We try only with the AttachInfo because there's no point in invalidating @@ -9391,6 +9407,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * @param top The top coordinate of the rectangle to invalidate. * @param right The right coordinate of the rectangle to invalidate. * @param bottom The bottom coordinate of the rectangle to invalidate. + * + * @see #invalidate(int, int, int, int) + * @see #invalidate(Rect) + * @see #postInvalidate(int, int, int, int) */ public void postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom) { @@ -9417,7 +9437,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * <p>This method can be invoked from outside of the UI thread * only when this View is attached to a window.</p> * - * @hide + * @see #invalidate() */ public void postInvalidateOnAnimation() { // We try only with the AttachInfo because there's no point in invalidating @@ -9440,7 +9460,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * @param right The right coordinate of the rectangle to invalidate. * @param bottom The bottom coordinate of the rectangle to invalidate. * - * @hide + * @see #invalidate(int, int, int, int) + * @see #invalidate(Rect) */ public void postInvalidateOnAnimation(int left, int top, int right, int bottom) { // We try only with the AttachInfo because there's no point in invalidating @@ -9769,7 +9790,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * @attr ref android.R.styleable#View_scrollbarSize */ public int getScrollBarSize() { - return mScrollCache == null ? ViewConfiguration.getScrollBarSize() : + return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() : mScrollCache.scrollBarSize; } @@ -12948,6 +12969,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * background */ public void setBackground(Drawable background) { + //noinspection deprecation setBackgroundDrawable(background); } @@ -14273,7 +14295,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal */ public void setAnimation(Animation animation) { mCurrentAnimation = animation; + if (animation != null) { + // If the screen is off assume the animation start time is now instead of + // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time + // would cause the animation to start when the screen turns back on + if (mAttachInfo != null && !mAttachInfo.mScreenOn && + animation.getStartTime() == Animation.START_ON_FIRST_FRAME) { + animation.setStartTime(AnimationUtils.currentAnimationTimeMillis()); + } animation.reset(); } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 899fb32..2e3ff38 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -5065,6 +5065,19 @@ public final class ViewRootImpl implements ViewParent, } /** + * Computes whether a view is visible on the screen. + * + * @param view The view to check. + * @return Whether the view is visible on the screen. + */ + private boolean isDisplayedOnScreen(View view) { + return (view.mAttachInfo != null + && view.mAttachInfo.mWindowVisibility == View.VISIBLE + && view.getVisibility() == View.VISIBLE + && view.getGlobalVisibleRect(mTempRect)); + } + + /** * Class for managing accessibility interactions initiated from the system * and targeting the view hierarchy. A *ClientThread method is to be * called from the interaction connection this ViewAncestor gives the @@ -5175,7 +5188,7 @@ public final class ViewRootImpl implements ViewParent, } else { target = findViewByAccessibilityId(accessibilityViewId); } - if (target != null && target.getVisibility() == View.VISIBLE) { + if (target != null && isDisplayedOnScreen(target)) { getAccessibilityNodePrefetcher().prefetchAccessibilityNodeInfos(target, virtualDescendantId, prefetchFlags, infos); } @@ -5231,7 +5244,7 @@ public final class ViewRootImpl implements ViewParent, } if (root != null) { View target = root.findViewById(viewId); - if (target != null && target.getVisibility() == View.VISIBLE) { + if (target != null && isDisplayedOnScreen(target)) { info = target.createAccessibilityNodeInfo(); } } @@ -5287,7 +5300,7 @@ public final class ViewRootImpl implements ViewParent, } else { target = ViewRootImpl.this.mView; } - if (target != null && target.getVisibility() == View.VISIBLE) { + if (target != null && isDisplayedOnScreen(target)) { AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider(); if (provider != null) { infos = provider.findAccessibilityNodeInfosByText(text, @@ -5304,7 +5317,7 @@ public final class ViewRootImpl implements ViewParent, final int viewCount = foundViews.size(); for (int i = 0; i < viewCount; i++) { View foundView = foundViews.get(i); - if (foundView.getVisibility() == View.VISIBLE) { + if (isDisplayedOnScreen(foundView)) { provider = foundView.getAccessibilityNodeProvider(); if (provider != null) { List<AccessibilityNodeInfo> infosFromProvider = @@ -5367,7 +5380,7 @@ public final class ViewRootImpl implements ViewParent, boolean succeeded = false; try { View target = findViewByAccessibilityId(accessibilityViewId); - if (target != null && target.getVisibility() == View.VISIBLE) { + if (target != null && isDisplayedOnScreen(target)) { AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider(); if (provider != null) { succeeded = provider.performAccessibilityAction(action, @@ -5505,7 +5518,7 @@ public final class ViewRootImpl implements ViewParent, View child = parentGroup.getChildAt(i); if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE && child.getAccessibilityViewId() != current.getAccessibilityViewId() - && child.getVisibility() == View.VISIBLE) { + && isDisplayedOnScreen(child)) { final long childNodeId = AccessibilityNodeInfo.makeNodeId( child.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED); AccessibilityNodeInfo info = null; @@ -5533,7 +5546,7 @@ public final class ViewRootImpl implements ViewParent, final int childCount = rootGroup.getChildCount(); for (int i = 0; i < childCount; i++) { View child = rootGroup.getChildAt(i); - if (child.getVisibility() == View.VISIBLE + if (isDisplayedOnScreen(child) && outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) { final long childNodeId = AccessibilityNodeInfo.makeNodeId( child.getAccessibilityViewId(), AccessibilityNodeInfo.UNDEFINED); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index f3ef329..bc310b0 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -423,6 +423,12 @@ public interface WindowManager extends ViewManager { public static final int TYPE_HIDDEN_NAV_CONSUMER = FIRST_SYSTEM_WINDOW+22; /** + * Window type: Dreams (screen saver) window, just above keyguard. + * @hide + */ + public static final int TYPE_DREAM = FIRST_SYSTEM_WINDOW+23; + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index a45a87e..52bd860 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -432,23 +432,24 @@ public class WindowManagerImpl implements WindowManager { */ public void trimMemory(int level) { if (HardwareRenderer.isAvailable()) { - // On low and medium end gfx devices - if (!ActivityManager.isHighEndGfx(getDefaultDisplay())) { - if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) { - // Destroy all hardware surfaces and resources associated to - // known windows - synchronized (this) { - if (mViews == null) return; - int count = mViews.length; - for (int i = 0; i < count; i++) { - mRoots[i].terminateHardwareResources(); - } + // On low-end gfx devices we trim when memory is moderate; + // on high-end devices we do this when low. + if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE + || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE + && !ActivityManager.isHighEndGfx(getDefaultDisplay()))) { + // Destroy all hardware surfaces and resources associated to + // known windows + synchronized (this) { + if (mViews == null) return; + int count = mViews.length; + for (int i = 0; i < count; i++) { + mRoots[i].terminateHardwareResources(); } - // Force a full memory flush - HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); - mNeedsEglTerminate = true; - return; } + // Force a full memory flush + HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE); + mNeedsEglTerminate = true; + return; } HardwareRenderer.trimMemory(level); } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 491cd67..27baaea 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -667,7 +667,7 @@ public interface WindowManagerPolicy { /** * Create and return an animation to re-display a force hidden window. */ - public Animation createForceHideEnterAnimation(); + public Animation createForceHideEnterAnimation(boolean onWallpaper); /** * Called from the input reader thread before a key is enqueued. @@ -1049,6 +1049,31 @@ public interface WindowManagerPolicy { public void lockNow(); /** + * Check to see if a screensaver should be run instead of powering off the screen on timeout. + * + * @return true if the screensaver should run, false if the screen should turn off. + * + * @hide + */ + public boolean isScreenSaverEnabled(); + + /** + * Start the screensaver (if it is enabled and not yet running). + * + * @return Whether the screensaver was successfully started. + * + * @hide + */ + public boolean startScreenSaver(); + + /** + * Stop the screensaver if it is running. + * + * @hide + */ + public void stopScreenSaver(); + + /** * Print the WindowManagerPolicy's state into the given stream. * * @param prefix Text to print at the front of each line. diff --git a/core/java/android/webkit/AutoCompletePopup.java b/core/java/android/webkit/AutoCompletePopup.java index b26156c..21d5e02 100644 --- a/core/java/android/webkit/AutoCompletePopup.java +++ b/core/java/android/webkit/AutoCompletePopup.java @@ -129,13 +129,13 @@ class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener { } public void resetRect() { - int left = mWebView.contentToViewX(mWebView.mEditTextBounds.left); - int right = mWebView.contentToViewX(mWebView.mEditTextBounds.right); + int left = mWebView.contentToViewX(mWebView.mEditTextContentBounds.left); + int right = mWebView.contentToViewX(mWebView.mEditTextContentBounds.right); int width = right - left; mPopup.setWidth(width); - int bottom = mWebView.contentToViewY(mWebView.mEditTextBounds.bottom); - int top = mWebView.contentToViewY(mWebView.mEditTextBounds.top); + int bottom = mWebView.contentToViewY(mWebView.mEditTextContentBounds.bottom); + int top = mWebView.contentToViewY(mWebView.mEditTextContentBounds.top); int height = bottom - top; AbsoluteLayout.LayoutParams lp = diff --git a/core/java/android/webkit/DeviceMotionAndOrientationManager.java b/core/java/android/webkit/DeviceMotionAndOrientationManager.java index 79b78d8..ea1e9ff 100644 --- a/core/java/android/webkit/DeviceMotionAndOrientationManager.java +++ b/core/java/android/webkit/DeviceMotionAndOrientationManager.java @@ -22,9 +22,8 @@ package android.webkit; * * This could be part of WebViewCore, but have moved it to its own class to * avoid bloat there. - * @hide */ -public final class DeviceMotionAndOrientationManager { +final class DeviceMotionAndOrientationManager { private WebViewCore mWebViewCore; public DeviceMotionAndOrientationManager(WebViewCore webViewCore) { @@ -32,12 +31,12 @@ public final class DeviceMotionAndOrientationManager { } /** - * Sets whether the Page for this WebViewCore should use a mock DeviceOrientation + * Sets that the Page for this WebViewCore should use a mock DeviceOrientation * client. */ - public void useMock() { + public void setUseMock() { assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); - nativeUseMock(mWebViewCore); + nativeSetUseMock(mWebViewCore); } /** @@ -66,7 +65,7 @@ public final class DeviceMotionAndOrientationManager { } // Native functions - private static native void nativeUseMock(WebViewCore webViewCore); + private static native void nativeSetUseMock(WebViewCore webViewCore); private static native void nativeSetMockOrientation(WebViewCore webViewCore, boolean canProvideAlpha, double alpha, boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma); diff --git a/core/java/android/webkit/DeviceMotionService.java b/core/java/android/webkit/DeviceMotionService.java index b4d5759..9121429 100755 --- a/core/java/android/webkit/DeviceMotionService.java +++ b/core/java/android/webkit/DeviceMotionService.java @@ -153,6 +153,7 @@ final class DeviceMotionService implements SensorEventListener { * SensorEventListener implementation. * Callbacks happen on the thread on which we registered - the WebCore thread. */ + @Override public void onSensorChanged(SensorEvent event) { assert(event.values.length == 3); assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); @@ -170,6 +171,7 @@ final class DeviceMotionService implements SensorEventListener { } } + @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); } diff --git a/core/java/android/webkit/DeviceOrientationService.java b/core/java/android/webkit/DeviceOrientationService.java index 47c8ab7..2e8656c 100755 --- a/core/java/android/webkit/DeviceOrientationService.java +++ b/core/java/android/webkit/DeviceOrientationService.java @@ -184,6 +184,7 @@ final class DeviceOrientationService implements SensorEventListener { * SensorEventListener implementation. * Callbacks happen on the thread on which we registered - the WebCore thread. */ + @Override public void onSensorChanged(SensorEvent event) { assert(event.values.length == 3); assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); @@ -217,6 +218,7 @@ final class DeviceOrientationService implements SensorEventListener { } } + @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); } diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java index 6c331ac..6b7263c 100644 --- a/core/java/android/webkit/FindActionModeCallback.java +++ b/core/java/android/webkit/FindActionModeCallback.java @@ -148,8 +148,8 @@ class FindActionModeCallback implements ActionMode.Callback, TextWatcher, mInput.showSoftInput(mEditText, 0); } - public void updateMatchCount(int matchIndex, int matchCount, boolean isNewFind) { - if (!isNewFind) { + public void updateMatchCount(int matchIndex, int matchCount, boolean isEmptyFind) { + if (!isEmptyFind) { mNumberOfMatches = matchCount; mActiveMatchIndex = matchIndex; updateMatchesString(); diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 9492e38..d1cfc6b 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -313,7 +313,6 @@ public class WebView extends AbsoluteLayout /** * Interface to listen for find results. - * @hide */ public interface FindListener { /** @@ -1249,8 +1248,7 @@ public class WebView extends AbsoluteLayout * Register the listener to be notified as find-on-page operations progress. * This will replace the current listener. * - * @param listener An implementation of {@link WebView#FindListener}. - * @hide + * @param listener An implementation of {@link FindListener}. */ public void setFindListener(FindListener listener) { checkThread(); @@ -1258,11 +1256,15 @@ public class WebView extends AbsoluteLayout } /** - * Highlight and scroll to the next occurance of String in findAll. - * Wraps the page infinitely, and scrolls. Must be called after - * calling findAll. + * Highlight and scroll to the next match found by {@link #findAll} or + * {@link #findAllAsync}, wrapping around page boundaries as necessary. + * Notifies any registered {@link FindListener}. If neither + * {@link #findAll} nor {@link #findAllAsync(String)} has been called yet, + * or if {@link #clearMatches} has been called since the last find + * operation, this function does nothing. * * @param forward Direction to search. + * @see #setFindListener */ public void findNext(boolean forward) { checkThread(); @@ -1271,10 +1273,13 @@ public class WebView extends AbsoluteLayout /** * Find all instances of find on the page and highlight them. + * Notifies any registered {@link FindListener}. * * @param find String to find. * @return int The number of occurances of the String "find" * that were found. + * @deprecated {@link #findAllAsync} is preferred. + * @see #setFindListener */ public int findAll(String find) { checkThread(); @@ -1283,10 +1288,12 @@ public class WebView extends AbsoluteLayout /** * Find all instances of find on the page and highlight them, - * asynchronously. + * asynchronously. Notifies any registered {@link FindListener}. + * Successive calls to this or {@link #findAll} will cancel any + * pending searches. * * @param find String to find. - * @hide + * @see #setFindListener */ public void findAllAsync(String find) { checkThread(); @@ -1333,8 +1340,9 @@ public class WebView extends AbsoluteLayout return getFactory().getStatics().findAddress(addr); } - /* - * Clear the highlighting surrounding text matches created by findAll. + /** + * Clear the highlighting surrounding text matches created by + * {@link #findAll} or {@link #findAllAsync}. */ public void clearMatches() { checkThread(); @@ -1531,6 +1539,7 @@ public class WebView extends AbsoluteLayout * * @deprecated The built-in zoom mechanism is preferred, see * {@link WebSettings#setBuiltInZoomControls(boolean)}. + * @hide since API version 16. */ @Deprecated public View getZoomControls() { diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index 4c118ac..851fd22 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -57,6 +57,7 @@ import android.net.http.SslCertificate; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.provider.Settings; @@ -100,7 +101,6 @@ import android.webkit.WebView.PictureListener; import android.webkit.WebViewCore.DrawData; import android.webkit.WebViewCore.EventHub; import android.webkit.WebViewCore.TextFieldInitData; -import android.webkit.WebViewCore.TouchEventData; import android.webkit.WebViewCore.TouchHighlightData; import android.webkit.WebViewCore.WebKitHitTest; import android.widget.AbsoluteLayout; @@ -461,6 +461,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc selectionStart = Math.min(selectionStart, editable.length()); selectionEnd = Math.min(selectionEnd, editable.length()); setSelection(selectionStart, selectionEnd); + finishComposingText(); } public void replaceSelection(CharSequence text) { @@ -827,6 +828,13 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing // the screen all-the-time. Good for profiling our drawing code static private final boolean AUTO_REDRAW_HACK = false; + + // The rate at which edit text is scrolled in content pixels per millisecond + static private final float TEXT_SCROLL_RATE = 0.01f; + + // The presumed scroll rate for the first scroll of edit text + static private final long TEXT_SCROLL_FIRST_SCROLL_MS = 16; + // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK private boolean mAutoRedraw; @@ -846,12 +854,13 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc private int mFieldPointer; private PastePopupWindow mPasteWindow; private AutoCompletePopup mAutoCompletePopup; - Rect mEditTextBounds = new Rect(); + Rect mEditTextContentBounds = new Rect(); Rect mEditTextContent = new Rect(); int mEditTextLayerId; boolean mIsEditingText = false; ArrayList<Message> mBatchedTextChanges = new ArrayList<Message>(); boolean mIsBatchingTextChanges = false; + private long mLastEditScroll = 0; private static class OnTrimMemoryListener implements ComponentCallbacks2 { private static OnTrimMemoryListener sInstance = null; @@ -885,7 +894,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // the existing GL resources for the html5 video will be destroyed // at native side. // Here we just need to clean up the Surface Texture which is static. - HTML5VideoInline.cleanupSurfaceTexture(); + if (level >= TRIM_MEMORY_UI_HIDDEN) { + HTML5VideoInline.cleanupSurfaceTexture(); + } WebViewClassic.nativeOnTrimMemory(level); } @@ -978,6 +989,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc /** * Touch mode + * TODO: Some of this is now unnecessary as it is handled by + * WebInputTouchDispatcher (such as click, long press, and double tap). */ private int mTouchMode = TOUCH_DONE_MODE; private static final int TOUCH_INIT_MODE = 1; @@ -991,35 +1004,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc private static final int TOUCH_DRAG_LAYER_MODE = 9; private static final int TOUCH_DRAG_TEXT_MODE = 10; - // Whether to forward the touch events to WebCore - // Can only be set by WebKit via JNI. - private boolean mForwardTouchEvents = false; - - // Whether to prevent default during touch. The initial value depends on - // mForwardTouchEvents. If WebCore wants all the touch events, it says yes - // for touch down. Otherwise UI will wait for the answer of the first - // confirmed move before taking over the control. - private static final int PREVENT_DEFAULT_NO = 0; - private static final int PREVENT_DEFAULT_MAYBE_YES = 1; - private static final int PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN = 2; - private static final int PREVENT_DEFAULT_YES = 3; - private static final int PREVENT_DEFAULT_IGNORE = 4; - private int mPreventDefault = PREVENT_DEFAULT_IGNORE; - // true when the touch movement exceeds the slop private boolean mConfirmMove; private boolean mTouchInEditText; - // if true, touch events will be first processed by WebCore, if prevent - // default is not set, the UI will continue handle them. - private boolean mDeferTouchProcess; - - // to avoid interfering with the current touch events, track them - // separately. Currently no snapping or fling in the deferred process mode - private int mDeferTouchMode = TOUCH_DONE_MODE; - private float mLastDeferTouchX; - private float mLastDeferTouchY; - // Whether or not to draw the cursor ring. private boolean mDrawCursorRing = true; @@ -1057,9 +1045,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // pages with the space bar, in pixels. private static final int PAGE_SCROLL_OVERLAP = 24; - // Time between successive calls to text scroll fling animation - private static final int TEXT_SCROLL_ANIMATION_DELAY_MS = 16; - /** * These prevent calling requestLayout if either dimension is fixed. This * depends on the layout parameters and the measure specs. @@ -1227,9 +1212,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc static final int RELOCATE_AUTO_COMPLETE_POPUP = 146; static final int FOCUS_NODE_CHANGED = 147; static final int AUTOFILL_FORM = 148; - static final int ANIMATE_TEXT_SCROLL = 149; + static final int SCROLL_EDIT_TEXT = 149; static final int EDIT_TEXT_SIZE_CHANGED = 150; static final int SHOW_CARET_HANDLE = 151; + static final int UPDATE_CONTENT_BOUNDS = 152; private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID; private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT; @@ -1406,7 +1392,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc private boolean mSentAutoScrollMessage = false; // used for serializing asynchronously handled touch events. - private final TouchEventQueue mTouchEventQueue = new TouchEventQueue(); + private WebViewInputDispatcher mInputDispatcher; // Used to track whether picture updating was paused due to a window focus change. private boolean mPictureUpdatePausedForFocusChange = false; @@ -1496,6 +1482,68 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } + private void onHandleUiEvent(MotionEvent event, int eventType, int flags) { + switch (eventType) { + case WebViewInputDispatcher.EVENT_TYPE_LONG_PRESS: + HitTestResult hitTest = getHitTestResult(); + if (hitTest != null + && hitTest.getType() != HitTestResult.UNKNOWN_TYPE) { + performLongClick(); + } + break; + case WebViewInputDispatcher.EVENT_TYPE_DOUBLE_TAP: + mZoomManager.handleDoubleTap(event.getX(), event.getY()); + break; + case WebViewInputDispatcher.EVENT_TYPE_TOUCH: + onHandleUiTouchEvent(event); + break; + } + } + + private void onHandleUiTouchEvent(MotionEvent ev) { + final ScaleGestureDetector detector = + mZoomManager.getMultiTouchGestureDetector(); + + float x = ev.getX(); + float y = ev.getY(); + + if (detector != null) { + detector.onTouchEvent(ev); + if (detector.isInProgress()) { + mLastTouchTime = ev.getEventTime(); + x = detector.getFocusX(); + y = detector.getFocusY(); + + mWebView.cancelLongPress(); + mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); + if (!mZoomManager.supportsPanDuringZoom()) { + return; + } + mTouchMode = TOUCH_DRAG_MODE; + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + } + } + + int action = ev.getActionMasked(); + if (action == MotionEvent.ACTION_POINTER_DOWN) { + cancelTouch(); + action = MotionEvent.ACTION_DOWN; + } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() >= 2) { + // set mLastTouchX/Y to the remaining points for multi-touch. + mLastTouchX = Math.round(x); + mLastTouchY = Math.round(y); + } else if (action == MotionEvent.ACTION_MOVE) { + // negative x or y indicate it is on the edge, skip it. + if (x < 0 || y < 0) { + return; + } + } + + handleTouchEventCommon(ev, action, Math.round(x), Math.round(y)); + } + // The webview that is bound to this WebViewClassic instance. Primarily needed for supplying // as the first param in the WebViewClient and WebChromeClient callbacks. final private WebView mWebView; @@ -2865,7 +2913,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc if (rect.width() < mFocusedNode.mHitTestSlop) { // ignore bounding boxes that are too small continue; - } else if (left != NO_LEFTEDGE && rect.width() > readingWidth) { + } else if (rect.width() > readingWidth) { // stop when bounding box doesn't fit the screen width // at reading scale break; @@ -3588,7 +3636,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc @Override public void findNext(boolean forward) { if (0 == mNativeClass) return; // client isn't initialized - mWebViewCore.sendMessage(EventHub.FIND_NEXT, forward ? 1 : 0); + if (mFindRequest != null) { + mWebViewCore.sendMessage(EventHub.FIND_NEXT, forward ? 1 : 0, mFindRequest); + } } /** @@ -3605,28 +3655,26 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc private int findAllBody(String find, boolean isAsync) { if (0 == mNativeClass) return 0; // client isn't initialized - mLastFind = find; + mFindRequest = null; if (find == null) return 0; mWebViewCore.removeMessages(EventHub.FIND_ALL); - WebViewCore.FindAllRequest request = new - WebViewCore.FindAllRequest(find); + mFindRequest = new WebViewCore.FindAllRequest(find); if (isAsync) { - mWebViewCore.sendMessage(EventHub.FIND_ALL, request); + mWebViewCore.sendMessage(EventHub.FIND_ALL, mFindRequest); return 0; // no need to wait for response } - synchronized(request) { + synchronized(mFindRequest) { try { - mWebViewCore.sendMessageAtFrontOfQueue(EventHub.FIND_ALL, - request); - while (request.mMatchCount == -1) { - request.wait(); + mWebViewCore.sendMessageAtFrontOfQueue(EventHub.FIND_ALL, mFindRequest); + while (mFindRequest.mMatchCount == -1) { + mFindRequest.wait(); } } catch (InterruptedException e) { return 0; } + return mFindRequest.mMatchCount; } - return request.mMatchCount; } /** @@ -3657,7 +3705,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc return true; } if (text == null) { - text = mLastFind; + text = mFindRequest == null ? null : mFindRequest.mSearchText; } if (text != null) { mFindCallback.setText(text); @@ -3683,9 +3731,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // or not we draw the highlights for matches. private boolean mFindIsUp; - // Keep track of the last string sent, so we can search again when find is - // reopened. - private String mLastFind; + // Keep track of the last find request sent. + private WebViewCore.FindAllRequest mFindRequest = null; /** * Return the first substring consisting of the address of a physical @@ -3866,7 +3913,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } if (mAutoCompletePopup != null && mCurrentScrollingLayerId == mEditTextLayerId) { - mEditTextBounds.offset(dx, dy); + mEditTextContentBounds.offset(dx, dy); mAutoCompletePopup.resetRect(); } nativeScrollLayer(mCurrentScrollingLayerId, x, y); @@ -4369,8 +4416,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc boolean animateScroll = ((!mScroller.isFinished() || mVelocityTracker != null) && (mTouchMode != TOUCH_DRAG_MODE || - mHeldMotionless != MOTIONLESS_TRUE)) - || mDeferTouchMode == TOUCH_DRAG_MODE; + mHeldMotionless != MOTIONLESS_TRUE)); if (mTouchMode == TOUCH_DRAG_MODE) { if (mHeldMotionless == MOTIONLESS_PENDING) { mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS); @@ -5008,8 +5054,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc * * debug only */ - public void useMockDeviceOrientation() { - mWebViewCore.sendMessage(EventHub.USE_MOCK_DEVICE_ORIENTATION); + public void setUseMockDeviceOrientation() { + mWebViewCore.sendMessage(EventHub.SET_USE_MOCK_DEVICE_ORIENTATION); } /** @@ -5570,7 +5616,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc addAccessibilityApisToJavaScript(); - mTouchEventQueue.reset(); updateHwAccelerated(); } @@ -5819,20 +5864,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc */ private static final float MMA_WEIGHT_N = 5; - private boolean hitFocusedPlugin(int contentX, int contentY) { - // TODO: Figure out what to do with this (b/6111517) - return false; - } - - private boolean shouldForwardTouchEvent() { - if (mFullScreenHolder != null) return true; - if (mBlockWebkitViewMessages) return false; - return mForwardTouchEvents - && !mSelectingText - && mPreventDefault != PREVENT_DEFAULT_IGNORE - && mPreventDefault != PREVENT_DEFAULT_NO; - } - private boolean inFullScreenMode() { return mFullScreenHolder != null; } @@ -5902,23 +5933,17 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc mWebView.requestFocus(); } - if (DebugFlags.WEB_VIEW) { - Log.v(LOGTAG, ev + " at " + ev.getEventTime() - + " mTouchMode=" + mTouchMode - + " numPointers=" + ev.getPointerCount()); + if (mInputDispatcher == null) { + return false; } - // If WebKit wasn't interested in this multitouch gesture, enqueue - // the event for handling directly rather than making the round trip - // to WebKit and back. - if (ev.getPointerCount() > 1 && mPreventDefault != PREVENT_DEFAULT_NO) { - passMultiTouchToWebKit(ev, mTouchEventQueue.nextTouchSequence()); + if (mInputDispatcher.postPointerEvent(ev, getScrollX(), + getScrollY() - getTitleHeight(), mZoomManager.getInvScale())) { + return true; } else { - mTouchEventQueue.enqueueTouchEvent(ev); + Log.w(LOGTAG, "mInputDispatcher rejected the event!"); + return false; } - - // Since all events are handled asynchronously, we always want the gesture stream. - return true; } private float calculateDragAngle(int dx, int dy) { @@ -5928,12 +5953,14 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } /* - * Common code for single touch and multi-touch. - * (x, y) denotes current focus point, which is the touch point for single touch - * and the middle point for multi-touch. - */ - private boolean handleTouchEventCommon(MotionEvent ev, int action, int x, int y) { - long eventTime = ev.getEventTime(); + * Common code for single touch and multi-touch. + * (x, y) denotes current focus point, which is the touch point for single touch + * and the middle point for multi-touch. + */ + private void handleTouchEventCommon(MotionEvent event, int action, int x, int y) { + ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector(); + + long eventTime = event.getEventTime(); // Due to the touch screen edge effect, a touch closer to the edge // always snapped to the edge. As getViewWidth() can be different from @@ -5949,7 +5976,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc switch (action) { case MotionEvent.ACTION_DOWN: { - mPreventDefault = PREVENT_DEFAULT_NO; mConfirmMove = false; mInitialHitTestResult = null; if (!mEditTextScroller.isFinished()) { @@ -5969,20 +5995,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) { mTouchMode = TOUCH_DOUBLE_TAP_MODE; } else { - // commit the short press action for the previous tap - doShortPress(); mTouchMode = TOUCH_INIT_MODE; - mDeferTouchProcess = !mBlockWebkitViewMessages - && (!inFullScreenMode() && mForwardTouchEvents) - ? hitFocusedPlugin(contentX, contentY) - : false; } } else { // the normal case mTouchMode = TOUCH_INIT_MODE; - mDeferTouchProcess = !mBlockWebkitViewMessages - && (!inFullScreenMode() && mForwardTouchEvents) - ? hitFocusedPlugin(contentX, contentY) - : false; + // TODO: Have WebViewInputDispatch handle this TouchHighlightData data = new TouchHighlightData(); data.mX = contentX; data.mY = contentY; @@ -5990,25 +6007,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc data.mNativeLayer = nativeScrollableLayer( contentX, contentY, data.mNativeLayerRect, null); data.mSlop = viewToContentDimension(mNavSlop); - mTouchHighlightRegion.setEmpty(); + removeTouchHighlight(); if (!mBlockWebkitViewMessages) { - mTouchHighlightRequested = System.currentTimeMillis(); + mTouchHighlightRequested = SystemClock.uptimeMillis(); mWebViewCore.sendMessageAtFrontOfQueue( EventHub.HIT_TEST, data); } - if (DEBUG_TOUCH_HIGHLIGHT) { - if (getSettings().getNavDump()) { - mTouchHighlightX = x + getScrollX(); - mTouchHighlightY = y + getScrollY(); - mPrivateHandler.postDelayed(new Runnable() { - @Override - public void run() { - mTouchHighlightX = mTouchHighlightY = 0; - invalidate(); - } - }, TOUCH_HIGHLIGHT_ELAPSE_TIME); - } - } if (mLogEvent && eventTime - mLastTouchUpTime < 1000) { EventLog.writeEvent(EventLogTags.BROWSER_DOUBLE_TAP_DURATION, (eventTime - mLastTouchUpTime), eventTime); @@ -6055,58 +6059,20 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc SWITCH_TO_SHORTPRESS, TAP_TIMEOUT); mPrivateHandler.sendEmptyMessageDelayed( SWITCH_TO_LONGPRESS, LONG_PRESS_TIMEOUT); - if (inFullScreenMode() || mDeferTouchProcess) { - mPreventDefault = PREVENT_DEFAULT_YES; - } else if (!mBlockWebkitViewMessages && mForwardTouchEvents) { - mPreventDefault = PREVENT_DEFAULT_MAYBE_YES; - } else { - mPreventDefault = PREVENT_DEFAULT_NO; - } - // pass the touch events from UI thread to WebCore thread - if (shouldForwardTouchEvent()) { - TouchEventData ted = new TouchEventData(); - ted.mAction = action; - ted.mIds = new int[1]; - ted.mIds[0] = ev.getPointerId(0); - ted.mPoints = new Point[1]; - ted.mPoints[0] = new Point(contentX, contentY); - ted.mPointsInView = new Point[1]; - ted.mPointsInView[0] = new Point(x, y); - ted.mMetaState = ev.getMetaState(); - ted.mReprocess = mDeferTouchProcess; - ted.mNativeLayer = nativeScrollableLayer( - contentX, contentY, ted.mNativeLayerRect, null); - ted.mSequence = mTouchEventQueue.nextTouchSequence(); - mTouchEventQueue.preQueueTouchEventData(ted); - mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); - if (mDeferTouchProcess) { - // still needs to set them for compute deltaX/Y - mLastTouchX = x; - mLastTouchY = y; - break; - } - if (!inFullScreenMode()) { - mPrivateHandler.removeMessages(PREVENT_DEFAULT_TIMEOUT); - mPrivateHandler.sendMessageDelayed(mPrivateHandler - .obtainMessage(PREVENT_DEFAULT_TIMEOUT, - action, 0), TAP_TIMEOUT); - } - } } startTouch(x, y, eventTime); if (mIsEditingText) { - mTouchInEditText = mEditTextBounds.contains(contentX, contentY); + mTouchInEditText = mEditTextContentBounds + .contains(contentX, contentY); } break; } case MotionEvent.ACTION_MOVE: { - boolean firstMove = false; if (!mConfirmMove && (deltaX * deltaX + deltaY * deltaY) >= mTouchSlopSquare) { mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS); mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); mConfirmMove = true; - firstMove = true; if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) { mTouchMode = TOUCH_INIT_MODE; } @@ -6121,8 +6087,28 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc parent.requestDisallowInterceptTouchEvent(true); } if (deltaX != 0 || deltaY != 0) { - snapDraggingCursor(contentX, contentY); + int handleX = contentX + + viewToContentDimension(mSelectDraggingOffset.x); + int handleY = contentY + + viewToContentDimension(mSelectDraggingOffset.y); + mSelectDraggingCursor.set(handleX, handleY); + boolean inCursorText = + mSelectDraggingTextQuad.containsPoint(handleX, handleY); + boolean inEditBounds = mEditTextContentBounds + .contains(handleX, handleY); + if (mIsEditingText && !inEditBounds) { + beginScrollEdit(); + } else { + endScrollEdit(); + } + if (inCursorText || (mIsEditingText && !inEditBounds)) { + snapDraggingCursor(); + } updateWebkitSelection(); + if (!inCursorText && mIsEditingText && inEditBounds) { + // Visually snap even if we have moved the handle. + snapDraggingCursor(); + } mLastTouchX = x; mLastTouchY = y; invalidate(); @@ -6130,48 +6116,16 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc break; } - // pass the touch events from UI thread to WebCore thread - if (shouldForwardTouchEvent() && mConfirmMove && (firstMove - || eventTime - mLastSentTouchTime > mCurrentTouchInterval)) { - TouchEventData ted = new TouchEventData(); - ted.mAction = action; - ted.mIds = new int[1]; - ted.mIds[0] = ev.getPointerId(0); - ted.mPoints = new Point[1]; - ted.mPoints[0] = new Point(contentX, contentY); - ted.mPointsInView = new Point[1]; - ted.mPointsInView[0] = new Point(x, y); - ted.mMetaState = ev.getMetaState(); - ted.mReprocess = mDeferTouchProcess; - ted.mNativeLayer = mCurrentScrollingLayerId; - ted.mNativeLayerRect.set(mScrollingLayerRect); - ted.mMotionEvent = MotionEvent.obtain(ev); - ted.mSequence = mTouchEventQueue.nextTouchSequence(); - mTouchEventQueue.preQueueTouchEventData(ted); - mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); - mLastSentTouchTime = eventTime; - if (mDeferTouchProcess) { - break; - } - if (firstMove && !inFullScreenMode()) { - mPrivateHandler.sendMessageDelayed(mPrivateHandler - .obtainMessage(PREVENT_DEFAULT_TIMEOUT, - action, 0), TAP_TIMEOUT); - } - } - if (mTouchMode == TOUCH_DONE_MODE - || mPreventDefault == PREVENT_DEFAULT_YES) { + if (mTouchMode == TOUCH_DONE_MODE) { // no dragging during scroll zoom animation, or when prevent // default is yes break; } if (mVelocityTracker == null) { Log.e(LOGTAG, "Got null mVelocityTracker when " - + "mPreventDefault = " + mPreventDefault - + " mDeferTouchProcess = " + mDeferTouchProcess + " mTouchMode = " + mTouchMode); } else { - mVelocityTracker.addMovement(ev); + mVelocityTracker.addMovement(event); } if (mTouchMode != TOUCH_DRAG_MODE && @@ -6182,19 +6136,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc break; } - if (mPreventDefault == PREVENT_DEFAULT_MAYBE_YES - || mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) { - // track mLastTouchTime as we may need to do fling at - // ACTION_UP - mLastTouchTime = eventTime; - break; - } - // Only lock dragging to one axis if we don't have a scale in progress. // Scaling implies free-roaming movement. Note this is only ever a question // if mZoomManager.supportsPanDuringZoom() is true. - final ScaleGestureDetector detector = - mZoomManager.getMultiTouchGestureDetector(); mAverageAngle = calculateDragAngle(deltaX, deltaY); if (detector == null || !detector.isInProgress()) { // if it starts nearly horizontal or vertical, enforce it @@ -6220,10 +6164,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } // do pan - boolean done = false; boolean keepScrollBarsVisible = false; if (deltaX == 0 && deltaY == 0) { - keepScrollBarsVisible = done = true; + keepScrollBarsVisible = true; } else { mAverageAngle += (calculateDragAngle(deltaX, deltaY) - mAverageAngle) @@ -6300,37 +6243,20 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc ViewConfiguration.getScrollDefaultDelay()); // return false to indicate that we can't pan out of the // view space - return !done; + return; } else { mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS); } break; } case MotionEvent.ACTION_UP: { + endScrollEdit(); if (!mConfirmMove && mIsEditingText && mSelectionStarted && mIsCaretSelection) { showPasteWindow(); stopTouch(); break; } - // pass the touch events from UI thread to WebCore thread - if (shouldForwardTouchEvent()) { - TouchEventData ted = new TouchEventData(); - ted.mIds = new int[1]; - ted.mIds[0] = ev.getPointerId(0); - ted.mAction = action; - ted.mPoints = new Point[1]; - ted.mPoints[0] = new Point(contentX, contentY); - ted.mPointsInView = new Point[1]; - ted.mPointsInView[0] = new Point(x, y); - ted.mMetaState = ev.getMetaState(); - ted.mReprocess = mDeferTouchProcess; - ted.mNativeLayer = mCurrentScrollingLayerId; - ted.mNativeLayerRect.set(mScrollingLayerRect); - ted.mSequence = mTouchEventQueue.nextTouchSequence(); - mTouchEventQueue.preQueueTouchEventData(ted); - mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); - } mLastTouchUpTime = eventTime; if (mSentAutoScrollMessage) { mAutoScrollX = mAutoScrollY = 0; @@ -6339,66 +6265,14 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc case TOUCH_DOUBLE_TAP_MODE: // double tap mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS); mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); - if (inFullScreenMode() || mDeferTouchProcess) { - TouchEventData ted = new TouchEventData(); - ted.mIds = new int[1]; - ted.mIds[0] = ev.getPointerId(0); - ted.mAction = WebViewCore.ACTION_DOUBLETAP; - ted.mPoints = new Point[1]; - ted.mPoints[0] = new Point(contentX, contentY); - ted.mPointsInView = new Point[1]; - ted.mPointsInView[0] = new Point(x, y); - ted.mMetaState = ev.getMetaState(); - ted.mReprocess = mDeferTouchProcess; - ted.mNativeLayer = nativeScrollableLayer( - contentX, contentY, - ted.mNativeLayerRect, null); - ted.mSequence = mTouchEventQueue.nextTouchSequence(); - mTouchEventQueue.preQueueTouchEventData(ted); - mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); - } else if (mPreventDefault != PREVENT_DEFAULT_YES){ - mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); - mTouchMode = TOUCH_DONE_MODE; - } + mTouchMode = TOUCH_DONE_MODE; break; case TOUCH_INIT_MODE: // tap case TOUCH_SHORTPRESS_START_MODE: case TOUCH_SHORTPRESS_MODE: mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS); mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); - if (mConfirmMove) { - Log.w(LOGTAG, "Miss a drag as we are waiting for" + - " WebCore's response for touch down."); - if (mPreventDefault != PREVENT_DEFAULT_YES - && (computeMaxScrollX() > 0 - || computeMaxScrollY() > 0)) { - // If the user has performed a very quick touch - // sequence it is possible that we may get here - // before WebCore has had a chance to process the events. - // In this case, any call to preventDefault in the - // JS touch handler will not have been executed yet. - // Hence we will see both the UI (now) and WebCore - // (when context switches) handling the event, - // regardless of whether the web developer actually - // doeses preventDefault in their touch handler. This - // is the nature of our asynchronous touch model. - - // we will not rewrite drag code here, but we - // will try fling if it applies. - WebViewCore.reducePriority(); - // to get better performance, pause updating the - // picture - WebViewCore.pauseUpdatePicture(mWebViewCore); - // fall through to TOUCH_DRAG_MODE - } else { - // WebKit may consume the touch event and modify - // DOM. drawContentPicture() will be called with - // animateSroll as true for better performance. - // Force redraw in high-quality. - invalidate(); - break; - } - } else { + if (!mConfirmMove) { if (mSelectingText) { // tapping on selection or controls does nothing if (!mSelectionStarted) { @@ -6413,8 +6287,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc mPrivateHandler.sendEmptyMessageDelayed( RELEASE_SINGLE_TAP, ViewConfiguration .getDoubleTapTimeout()); - } else { - doShortPress(); } break; } @@ -6427,13 +6299,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc // up, we don't want to do a fling if (eventTime - mLastTouchTime <= MIN_FLING_TIME) { if (mVelocityTracker == null) { - Log.e(LOGTAG, "Got null mVelocityTracker when " - + "mPreventDefault = " - + mPreventDefault - + " mDeferTouchProcess = " - + mDeferTouchProcess); + Log.e(LOGTAG, "Got null mVelocityTracker"); } else { - mVelocityTracker.addMovement(ev); + mVelocityTracker.addMovement(event); } // set to MOTIONLESS_IGNORE so that it won't keep // removing and sending message in @@ -6472,126 +6340,88 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc computeMaxScrollX(), 0, computeMaxScrollY()); invalidate(); } - cancelWebCoreTouchEvent(contentX, contentY, false); cancelTouch(); break; } } - return true; } - private void passMultiTouchToWebKit(MotionEvent ev, long sequence) { - TouchEventData ted = new TouchEventData(); - ted.mAction = ev.getActionMasked(); - final int count = ev.getPointerCount(); - ted.mIds = new int[count]; - ted.mPoints = new Point[count]; - ted.mPointsInView = new Point[count]; - for (int c = 0; c < count; c++) { - ted.mIds[c] = ev.getPointerId(c); - int x = viewToContentX((int) ev.getX(c) + getScrollX()); - int y = viewToContentY((int) ev.getY(c) + getScrollY()); - ted.mPoints[c] = new Point(x, y); - ted.mPointsInView[c] = new Point((int) ev.getX(c), (int) ev.getY(c)); - } - if (ted.mAction == MotionEvent.ACTION_POINTER_DOWN - || ted.mAction == MotionEvent.ACTION_POINTER_UP) { - ted.mActionIndex = ev.getActionIndex(); - } - ted.mMetaState = ev.getMetaState(); - ted.mReprocess = true; - ted.mMotionEvent = MotionEvent.obtain(ev); - ted.mSequence = sequence; - mTouchEventQueue.preQueueTouchEventData(ted); - mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); - mWebView.cancelLongPress(); - mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); + /** + * Returns the text scroll speed in content pixels per millisecond based on + * the touch location. + * @param coordinate The x or y touch coordinate in content space + * @param min The minimum coordinate (x or y) of the edit content bounds + * @param max The maximum coordinate (x or y) of the edit content bounds + */ + private static float getTextScrollSpeed(int coordinate, int min, int max) { + if (coordinate < min) { + return (coordinate - min) * TEXT_SCROLL_RATE; + } else if (coordinate >= max) { + return (coordinate - max + 1) * TEXT_SCROLL_RATE; + } else { + return 0.0f; + } } - void handleMultiTouchInWebView(MotionEvent ev) { - if (DebugFlags.WEB_VIEW) { - Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime() - + " mTouchMode=" + mTouchMode - + " numPointers=" + ev.getPointerCount() - + " scrolloffset=(" + getScrollX() + "," + getScrollY() + ")"); + private void beginScrollEdit() { + if (mLastEditScroll == 0) { + mLastEditScroll = SystemClock.uptimeMillis() - + TEXT_SCROLL_FIRST_SCROLL_MS; + scrollEditWithCursor(); } + } - final ScaleGestureDetector detector = - mZoomManager.getMultiTouchGestureDetector(); - - // A few apps use WebView but don't instantiate gesture detector. - // We don't need to support multi touch for them. - if (detector == null) return; - - float x = ev.getX(); - float y = ev.getY(); - - if (mPreventDefault != PREVENT_DEFAULT_YES) { - detector.onTouchEvent(ev); - - if (detector.isInProgress()) { - if (DebugFlags.WEB_VIEW) { - Log.v(LOGTAG, "detector is in progress"); - } - mLastTouchTime = ev.getEventTime(); - x = detector.getFocusX(); - y = detector.getFocusY(); - - mWebView.cancelLongPress(); - mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); - if (!mZoomManager.supportsPanDuringZoom()) { - return; - } - mTouchMode = TOUCH_DRAG_MODE; - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - } - } + private void endScrollEdit() { + mLastEditScroll = 0; + } - int action = ev.getActionMasked(); - if (action == MotionEvent.ACTION_POINTER_DOWN) { - cancelTouch(); - action = MotionEvent.ACTION_DOWN; - } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() >= 2) { - // set mLastTouchX/Y to the remaining points for multi-touch. - mLastTouchX = Math.round(x); - mLastTouchY = Math.round(y); - } else if (action == MotionEvent.ACTION_MOVE) { - // negative x or y indicate it is on the edge, skip it. - if (x < 0 || y < 0) { - return; - } + private static int getTextScrollDelta(float speed, long deltaT) { + float distance = speed * deltaT; + int intDistance = (int)Math.floor(distance); + float probability = distance - intDistance; + if (Math.random() < probability) { + intDistance++; } - - handleTouchEventCommon(ev, action, Math.round(x), Math.round(y)); + return intDistance; } - - private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) { - if (shouldForwardTouchEvent()) { - if (removeEvents) { - mWebViewCore.removeMessages(EventHub.TOUCH_EVENT); - } - TouchEventData ted = new TouchEventData(); - ted.mIds = new int[1]; - ted.mIds[0] = 0; - ted.mPoints = new Point[1]; - ted.mPoints[0] = new Point(x, y); - ted.mPointsInView = new Point[1]; - int viewX = contentToViewX(x) - getScrollX(); - int viewY = contentToViewY(y) - getScrollY(); - ted.mPointsInView[0] = new Point(viewX, viewY); - ted.mAction = MotionEvent.ACTION_CANCEL; - ted.mNativeLayer = nativeScrollableLayer( - x, y, ted.mNativeLayerRect, null); - ted.mSequence = mTouchEventQueue.nextTouchSequence(); - mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); - mPreventDefault = PREVENT_DEFAULT_IGNORE; - - if (removeEvents) { - // Mark this after sending the message above; we should - // be willing to ignore the cancel event that we just sent. - mTouchEventQueue.ignoreCurrentlyMissingEvents(); + /** + * Scrolls edit text a distance based on the last touch point, + * the last scroll time, and the edit text content bounds. + */ + private void scrollEditWithCursor() { + if (mLastEditScroll != 0) { + int x = viewToContentX(mLastTouchX + getScrollX() + mSelectDraggingOffset.x); + float scrollSpeedX = getTextScrollSpeed(x, mEditTextContentBounds.left, + mEditTextContentBounds.right); + int y = viewToContentY(mLastTouchY + getScrollY() + mSelectDraggingOffset.y); + float scrollSpeedY = getTextScrollSpeed(y, mEditTextContentBounds.top, + mEditTextContentBounds.bottom); + if (scrollSpeedX == 0.0f && scrollSpeedY == 0.0f) { + endScrollEdit(); + } else { + long currentTime = SystemClock.uptimeMillis(); + long timeSinceLastUpdate = currentTime - mLastEditScroll; + int deltaX = getTextScrollDelta(scrollSpeedX, timeSinceLastUpdate); + int deltaY = getTextScrollDelta(scrollSpeedY, timeSinceLastUpdate); + mLastEditScroll = currentTime; + if (deltaX == 0 && deltaY == 0) { + // By probability no text scroll this time. Try again later. + mPrivateHandler.sendEmptyMessageDelayed(SCROLL_EDIT_TEXT, + TEXT_SCROLL_FIRST_SCROLL_MS); + } else { + int scrollX = getTextScrollX() + deltaX; + scrollX = Math.min(getMaxTextScrollX(), scrollX); + scrollX = Math.max(0, scrollX); + int scrollY = getTextScrollY() + deltaY; + scrollY = Math.min(getMaxTextScrollY(), scrollY); + scrollY = Math.max(0, scrollY); + scrollEditText(scrollX, scrollY); + int cursorX = mSelectDraggingCursor.x; + int cursorY = mSelectDraggingCursor.y; + mSelectDraggingCursor.set(x - deltaX, y - deltaY); + updateWebkitSelection(); + mSelectDraggingCursor.set(cursorX, cursorY); + } } } } @@ -6736,23 +6566,22 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc mTouchMode = TOUCH_DONE_MODE; } - private void snapDraggingCursor(int x, int y) { - x += viewToContentDimension(mSelectDraggingOffset.x); - y += viewToContentDimension(mSelectDraggingOffset.y); - if (mSelectDraggingTextQuad.containsPoint(x, y)) { - float scale = scaleAlongSegment(x, y, - mSelectDraggingTextQuad.p4, mSelectDraggingTextQuad.p3); - // clamp scale to ensure point is on the bottom segment - scale = Math.max(0.0f, scale); - scale = Math.min(scale, 1.0f); - float newX = scaleCoordinate(scale, - mSelectDraggingTextQuad.p4.x, mSelectDraggingTextQuad.p3.x); - float newY = scaleCoordinate(scale, - mSelectDraggingTextQuad.p4.y, mSelectDraggingTextQuad.p3.y); - mSelectDraggingCursor.set(Math.round(newX), Math.round(newY)); - } else { - mSelectDraggingCursor.set(x, y); - } + private void snapDraggingCursor() { + float scale = scaleAlongSegment( + mSelectDraggingCursor.x, mSelectDraggingCursor.y, + mSelectDraggingTextQuad.p4, mSelectDraggingTextQuad.p3); + // clamp scale to ensure point is on the bottom segment + scale = Math.max(0.0f, scale); + scale = Math.min(scale, 1.0f); + float newX = scaleCoordinate(scale, + mSelectDraggingTextQuad.p4.x, mSelectDraggingTextQuad.p3.x); + float newY = scaleCoordinate(scale, + mSelectDraggingTextQuad.p4.y, mSelectDraggingTextQuad.p3.y); + int x = Math.max(mEditTextContentBounds.left, + Math.min(mEditTextContentBounds.right, Math.round(newX))); + int y = Math.max(mEditTextContentBounds.top, + Math.min(mEditTextContentBounds.bottom, Math.round(newY))); + mSelectDraggingCursor.set(x, y); } private static float scaleCoordinate(float scale, float coord1, float coord2) { @@ -7231,39 +7060,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc return mZoomManager.zoomOut(); } - private void doShortPress() { - if (mNativeClass == 0) { - return; - } - if (mPreventDefault == PREVENT_DEFAULT_YES) { - return; - } - mTouchMode = TOUCH_DONE_MODE; - switchOutDrawHistory(); - if (!mTouchHighlightRegion.isEmpty()) { - // set mTouchHighlightRequested to 0 to cause an immediate - // drawing of the touch rings - mTouchHighlightRequested = 0; - mWebView.invalidate(mTouchHighlightRegion.getBounds()); - mPrivateHandler.postDelayed(new Runnable() { - @Override - public void run() { - removeTouchHighlight(); - } - }, ViewConfiguration.getPressedStateDuration()); - } - if (mFocusedNode != null && mFocusedNode.mIntentUrl != null) { - mWebView.playSoundEffect(SoundEffectConstants.CLICK); - overrideLoading(mFocusedNode.mIntentUrl); - } else { - WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData(); - // use "0" as generation id to inform WebKit to use the same x/y as - // it used when processing GET_TOUCH_HIGHLIGHT_RECTS - touchUpData.mMoveGeneration = 0; - mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData); - } - } - /* * Return true if the rect (e.g. plugin) is fully visible and maximized * inside the WebView. @@ -7544,490 +7340,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } private int getMaxTextScrollX() { - return Math.max(0, mEditTextContent.width() - mEditTextBounds.width()); + return Math.max(0, mEditTextContent.width() - mEditTextContentBounds.width()); } private int getMaxTextScrollY() { - return Math.max(0, mEditTextContent.height() - mEditTextBounds.height()); - } - - /** - * Used only by TouchEventQueue to store pending touch events. - */ - private static class QueuedTouch { - long mSequence; - MotionEvent mEvent; // Optional - TouchEventData mTed; // Optional - - QueuedTouch mNext; - - public QueuedTouch set(TouchEventData ted) { - mSequence = ted.mSequence; - mTed = ted; - mEvent = null; - mNext = null; - return this; - } - - public QueuedTouch set(MotionEvent ev, long sequence) { - mEvent = MotionEvent.obtain(ev); - mSequence = sequence; - mTed = null; - mNext = null; - return this; - } - - public QueuedTouch add(QueuedTouch other) { - if (other.mSequence < mSequence) { - other.mNext = this; - return other; - } - - QueuedTouch insertAt = this; - while (insertAt.mNext != null && insertAt.mNext.mSequence < other.mSequence) { - insertAt = insertAt.mNext; - } - other.mNext = insertAt.mNext; - insertAt.mNext = other; - return this; - } - } - - /** - * WebView handles touch events asynchronously since some events must be passed to WebKit - * for potentially slower processing. TouchEventQueue serializes touch events regardless - * of which path they take to ensure that no events are ever processed out of order - * by WebView. - */ - private class TouchEventQueue { - private long mNextTouchSequence = Long.MIN_VALUE + 1; - private long mLastHandledTouchSequence = Long.MIN_VALUE; - private long mIgnoreUntilSequence = Long.MIN_VALUE + 1; - - // Events waiting to be processed. - private QueuedTouch mTouchEventQueue; - - // Known events that are waiting on a response before being enqueued. - private QueuedTouch mPreQueue; - - // Pool of QueuedTouch objects saved for later use. - private QueuedTouch mQueuedTouchRecycleBin; - private int mQueuedTouchRecycleCount; - - private long mLastEventTime = Long.MAX_VALUE; - private static final int MAX_RECYCLED_QUEUED_TOUCH = 15; - - // milliseconds until we abandon hope of getting all of a previous gesture - private static final int QUEUED_GESTURE_TIMEOUT = 1000; - - private QueuedTouch obtainQueuedTouch() { - if (mQueuedTouchRecycleBin != null) { - QueuedTouch result = mQueuedTouchRecycleBin; - mQueuedTouchRecycleBin = result.mNext; - mQueuedTouchRecycleCount--; - return result; - } - return new QueuedTouch(); - } - - /** - * Allow events with any currently missing sequence numbers to be skipped in processing. - */ - public void ignoreCurrentlyMissingEvents() { - mIgnoreUntilSequence = mNextTouchSequence; - - // Run any events we have available and complete, pre-queued or otherwise. - runQueuedAndPreQueuedEvents(); - } - - private void runQueuedAndPreQueuedEvents() { - QueuedTouch qd = mPreQueue; - boolean fromPreQueue = true; - while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) { - handleQueuedTouch(qd); - QueuedTouch recycleMe = qd; - if (fromPreQueue) { - mPreQueue = qd.mNext; - } else { - mTouchEventQueue = qd.mNext; - } - recycleQueuedTouch(recycleMe); - mLastHandledTouchSequence++; - - long nextPre = mPreQueue != null ? mPreQueue.mSequence : Long.MAX_VALUE; - long nextQueued = mTouchEventQueue != null ? - mTouchEventQueue.mSequence : Long.MAX_VALUE; - fromPreQueue = nextPre < nextQueued; - qd = fromPreQueue ? mPreQueue : mTouchEventQueue; - } - } - - /** - * Add a TouchEventData to the pre-queue. - * - * An event in the pre-queue is an event that we know about that - * has been sent to webkit, but that we haven't received back and - * enqueued into the normal touch queue yet. If webkit ever times - * out and we need to ignore currently missing events, we'll run - * events from the pre-queue to patch the holes. - * - * @param ted TouchEventData to pre-queue - */ - public void preQueueTouchEventData(TouchEventData ted) { - QueuedTouch newTouch = obtainQueuedTouch().set(ted); - if (mPreQueue == null) { - mPreQueue = newTouch; - } else { - QueuedTouch insertionPoint = mPreQueue; - while (insertionPoint.mNext != null && - insertionPoint.mNext.mSequence < newTouch.mSequence) { - insertionPoint = insertionPoint.mNext; - } - newTouch.mNext = insertionPoint.mNext; - insertionPoint.mNext = newTouch; - } - } - - private void recycleQueuedTouch(QueuedTouch qd) { - if (mQueuedTouchRecycleCount < MAX_RECYCLED_QUEUED_TOUCH) { - qd.mNext = mQueuedTouchRecycleBin; - mQueuedTouchRecycleBin = qd; - mQueuedTouchRecycleCount++; - } - } - - /** - * Reset the touch event queue. This will dump any pending events - * and reset the sequence numbering. - */ - public void reset() { - mNextTouchSequence = Long.MIN_VALUE + 1; - mLastHandledTouchSequence = Long.MIN_VALUE; - mIgnoreUntilSequence = Long.MIN_VALUE + 1; - while (mTouchEventQueue != null) { - QueuedTouch recycleMe = mTouchEventQueue; - mTouchEventQueue = mTouchEventQueue.mNext; - recycleQueuedTouch(recycleMe); - } - while (mPreQueue != null) { - QueuedTouch recycleMe = mPreQueue; - mPreQueue = mPreQueue.mNext; - recycleQueuedTouch(recycleMe); - } - } - - /** - * Return the next valid sequence number for tagging incoming touch events. - * @return The next touch event sequence number - */ - public long nextTouchSequence() { - return mNextTouchSequence++; - } - - /** - * Enqueue a touch event in the form of TouchEventData. - * The sequence number will be read from the mSequence field of the argument. - * - * If the touch event's sequence number is the next in line to be processed, it will - * be handled before this method returns. Any subsequent events that have already - * been queued will also be processed in their proper order. - * - * @param ted Touch data to be processed in order. - * @return true if the event was processed before returning, false if it was just enqueued. - */ - public boolean enqueueTouchEvent(TouchEventData ted) { - // Remove from the pre-queue if present - QueuedTouch preQueue = mPreQueue; - if (preQueue != null) { - // On exiting this block, preQueue is set to the pre-queued QueuedTouch object - // if it was present in the pre-queue, and removed from the pre-queue itself. - if (preQueue.mSequence == ted.mSequence) { - mPreQueue = preQueue.mNext; - } else { - QueuedTouch prev = preQueue; - preQueue = null; - while (prev.mNext != null) { - if (prev.mNext.mSequence == ted.mSequence) { - preQueue = prev.mNext; - prev.mNext = preQueue.mNext; - break; - } else { - prev = prev.mNext; - } - } - } - } - - if (ted.mSequence < mLastHandledTouchSequence) { - // Stale event and we already moved on; drop it. (Should not be common.) - Log.w(LOGTAG, "Stale touch event " + MotionEvent.actionToString(ted.mAction) + - " received from webcore; ignoring"); - return false; - } - - if (dropStaleGestures(ted.mMotionEvent, ted.mSequence)) { - return false; - } - - // dropStaleGestures above might have fast-forwarded us to - // an event we have already. - runNextQueuedEvents(); - - if (mLastHandledTouchSequence + 1 == ted.mSequence) { - if (preQueue != null) { - recycleQueuedTouch(preQueue); - preQueue = null; - } - handleQueuedTouchEventData(ted); - - mLastHandledTouchSequence++; - - // Do we have any more? Run them if so. - runNextQueuedEvents(); - } else { - // Reuse the pre-queued object if we had it. - QueuedTouch qd = preQueue != null ? preQueue : obtainQueuedTouch().set(ted); - mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd); - } - return true; - } - - /** - * Enqueue a touch event in the form of a MotionEvent from the framework. - * - * If the touch event's sequence number is the next in line to be processed, it will - * be handled before this method returns. Any subsequent events that have already - * been queued will also be processed in their proper order. - * - * @param ev MotionEvent to be processed in order - */ - public void enqueueTouchEvent(MotionEvent ev) { - final long sequence = nextTouchSequence(); - - if (dropStaleGestures(ev, sequence)) { - return; - } - - // dropStaleGestures above might have fast-forwarded us to - // an event we have already. - runNextQueuedEvents(); - - if (mLastHandledTouchSequence + 1 == sequence) { - handleQueuedMotionEvent(ev); - - mLastHandledTouchSequence++; - - // Do we have any more? Run them if so. - runNextQueuedEvents(); - } else { - QueuedTouch qd = obtainQueuedTouch().set(ev, sequence); - mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd); - } - } - - private void runNextQueuedEvents() { - QueuedTouch qd = mTouchEventQueue; - while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) { - handleQueuedTouch(qd); - QueuedTouch recycleMe = qd; - qd = qd.mNext; - recycleQueuedTouch(recycleMe); - mLastHandledTouchSequence++; - } - mTouchEventQueue = qd; - } - - private boolean dropStaleGestures(MotionEvent ev, long sequence) { - if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && !mConfirmMove) { - // This is to make sure that we don't attempt to process a tap - // or long press when webkit takes too long to get back to us. - // The movement will be properly confirmed when we process the - // enqueued event later. - final int dx = Math.round(ev.getX()) - mLastTouchX; - final int dy = Math.round(ev.getY()) - mLastTouchY; - if (dx * dx + dy * dy > mTouchSlopSquare) { - mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS); - mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); - } - } - - if (mTouchEventQueue == null) { - return sequence <= mLastHandledTouchSequence; - } - - // If we have a new down event and it's been a while since the last event - // we saw, catch up as best we can and keep going. - if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN) { - long eventTime = ev.getEventTime(); - long lastHandledEventTime = mLastEventTime; - if (eventTime > lastHandledEventTime + QUEUED_GESTURE_TIMEOUT) { - Log.w(LOGTAG, "Got ACTION_DOWN but still waiting on stale event. " + - "Catching up."); - runQueuedAndPreQueuedEvents(); - - // Drop leftovers that we truly don't have. - QueuedTouch qd = mTouchEventQueue; - while (qd != null && qd.mSequence < sequence) { - QueuedTouch recycleMe = qd; - qd = qd.mNext; - recycleQueuedTouch(recycleMe); - } - mTouchEventQueue = qd; - mLastHandledTouchSequence = sequence - 1; - } - } - - if (mIgnoreUntilSequence - 1 > mLastHandledTouchSequence) { - QueuedTouch qd = mTouchEventQueue; - while (qd != null && qd.mSequence < mIgnoreUntilSequence) { - QueuedTouch recycleMe = qd; - qd = qd.mNext; - recycleQueuedTouch(recycleMe); - } - mTouchEventQueue = qd; - mLastHandledTouchSequence = mIgnoreUntilSequence - 1; - } - - if (mPreQueue != null) { - // Drop stale prequeued events - QueuedTouch qd = mPreQueue; - while (qd != null && qd.mSequence < mIgnoreUntilSequence) { - QueuedTouch recycleMe = qd; - qd = qd.mNext; - recycleQueuedTouch(recycleMe); - } - mPreQueue = qd; - } - - return sequence <= mLastHandledTouchSequence; - } - - private void handleQueuedTouch(QueuedTouch qt) { - if (qt.mTed != null) { - handleQueuedTouchEventData(qt.mTed); - } else { - handleQueuedMotionEvent(qt.mEvent); - qt.mEvent.recycle(); - } - } - - private void handleQueuedMotionEvent(MotionEvent ev) { - mLastEventTime = ev.getEventTime(); - int action = ev.getActionMasked(); - if (ev.getPointerCount() > 1) { // Multi-touch - handleMultiTouchInWebView(ev); - } else { - final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector(); - if (detector != null && mPreventDefault != PREVENT_DEFAULT_YES) { - // ScaleGestureDetector needs a consistent event stream to operate properly. - // It won't take any action with fewer than two pointers, but it needs to - // update internal bookkeeping state. - detector.onTouchEvent(ev); - } - - handleTouchEventCommon(ev, action, Math.round(ev.getX()), Math.round(ev.getY())); - } - } - - private void handleQueuedTouchEventData(TouchEventData ted) { - if (ted.mMotionEvent != null) { - mLastEventTime = ted.mMotionEvent.getEventTime(); - } - if (!ted.mReprocess) { - if (ted.mAction == MotionEvent.ACTION_DOWN - && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) { - // if prevent default is called from WebCore, UI - // will not handle the rest of the touch events any - // more. - mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES - : PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN; - } else if (ted.mAction == MotionEvent.ACTION_MOVE - && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) { - // the return for the first ACTION_MOVE will decide - // whether UI will handle touch or not. Currently no - // support for alternating prevent default - mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES - : PREVENT_DEFAULT_NO; - } - if (mPreventDefault == PREVENT_DEFAULT_YES) { - mTouchHighlightRegion.setEmpty(); - } - } else { - if (ted.mPoints.length > 1) { // multi-touch - if (!ted.mNativeResult && mPreventDefault != PREVENT_DEFAULT_YES) { - mPreventDefault = PREVENT_DEFAULT_NO; - handleMultiTouchInWebView(ted.mMotionEvent); - } else { - mPreventDefault = PREVENT_DEFAULT_YES; - } - return; - } - - // prevent default is not called in WebCore, so the - // message needs to be reprocessed in UI - if (!ted.mNativeResult) { - // Following is for single touch. - switch (ted.mAction) { - case MotionEvent.ACTION_DOWN: - mLastDeferTouchX = ted.mPointsInView[0].x; - mLastDeferTouchY = ted.mPointsInView[0].y; - mDeferTouchMode = TOUCH_INIT_MODE; - break; - case MotionEvent.ACTION_MOVE: { - // no snapping in defer process - int x = ted.mPointsInView[0].x; - int y = ted.mPointsInView[0].y; - - if (mDeferTouchMode != TOUCH_DRAG_MODE) { - mDeferTouchMode = TOUCH_DRAG_MODE; - mLastDeferTouchX = x; - mLastDeferTouchY = y; - startScrollingLayer(x, y); - startDrag(); - } - int deltaX = pinLocX((int) (getScrollX() - + mLastDeferTouchX - x)) - - getScrollX(); - int deltaY = pinLocY((int) (getScrollY() - + mLastDeferTouchY - y)) - - getScrollY(); - doDrag(deltaX, deltaY); - if (deltaX != 0) mLastDeferTouchX = x; - if (deltaY != 0) mLastDeferTouchY = y; - break; - } - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (mDeferTouchMode == TOUCH_DRAG_MODE) { - // no fling in defer process - mScroller.springBack(getScrollX(), getScrollY(), 0, - computeMaxScrollX(), 0, - computeMaxScrollY()); - invalidate(); - WebViewCore.resumePriority(); - WebViewCore.resumeUpdatePicture(mWebViewCore); - } - mDeferTouchMode = TOUCH_DONE_MODE; - break; - case WebViewCore.ACTION_DOUBLETAP: - // doDoubleTap() needs mLastTouchX/Y as anchor - mLastDeferTouchX = ted.mPointsInView[0].x; - mLastDeferTouchY = ted.mPointsInView[0].y; - mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); - mDeferTouchMode = TOUCH_DONE_MODE; - break; - case WebViewCore.ACTION_LONGPRESS: - HitTestResult hitTest = getHitTestResult(); - if (hitTest != null && hitTest.getType() - != HitTestResult.UNKNOWN_TYPE) { - performLongClick(); - } - mDeferTouchMode = TOUCH_DONE_MODE; - break; - } - } - } - } + return Math.max(0, mEditTextContent.height() - mEditTextContentBounds.height()); } //------------------------------------------------------------------------- @@ -8038,7 +7355,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc /** * General handler to receive message coming from webkit thread */ - class PrivateHandler extends Handler { + class PrivateHandler extends Handler implements WebViewInputDispatcher.UiCallbacks { @Override public void handleMessage(Message msg) { // exclude INVAL_RECT_MSG_ID since it is frequently output @@ -8079,20 +7396,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc ((Message) msg.obj).sendToTarget(); break; } - case PREVENT_DEFAULT_TIMEOUT: { - // if timeout happens, cancel it so that it won't block UI - // to continue handling touch events - if ((msg.arg1 == MotionEvent.ACTION_DOWN - && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) - || (msg.arg1 == MotionEvent.ACTION_MOVE - && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN)) { - cancelWebCoreTouchEvent( - viewToContentX(mLastTouchX + getScrollX()), - viewToContentY(mLastTouchY + getScrollY()), - true); - } - break; - } case SCROLL_SELECT_TEXT: { if (mAutoScrollX == 0 && mAutoScrollY == 0) { mSentAutoScrollMessage = false; @@ -8108,48 +7411,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL); break; } - case SWITCH_TO_SHORTPRESS: { - if (mTouchMode == TOUCH_INIT_MODE) { - mTouchMode = TOUCH_SHORTPRESS_MODE; - } else if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) { - mTouchMode = TOUCH_DONE_MODE; - } - break; - } - case SWITCH_TO_LONGPRESS: { - removeTouchHighlight(); - if (inFullScreenMode() || mDeferTouchProcess) { - TouchEventData ted = new TouchEventData(); - ted.mAction = WebViewCore.ACTION_LONGPRESS; - ted.mIds = new int[1]; - ted.mIds[0] = 0; - ted.mPoints = new Point[1]; - ted.mPoints[0] = new Point(viewToContentX(mLastTouchX + getScrollX()), - viewToContentY(mLastTouchY + getScrollY())); - ted.mPointsInView = new Point[1]; - ted.mPointsInView[0] = new Point(mLastTouchX, mLastTouchY); - // metaState for long press is tricky. Should it be the - // state when the press started or when the press was - // released? Or some intermediary key state? For - // simplicity for now, we don't set it. - ted.mMetaState = 0; - ted.mReprocess = mDeferTouchProcess; - ted.mNativeLayer = nativeScrollableLayer( - ted.mPoints[0].x, ted.mPoints[0].y, - ted.mNativeLayerRect, null); - ted.mSequence = mTouchEventQueue.nextTouchSequence(); - mTouchEventQueue.preQueueTouchEventData(ted); - mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); - } else if (mPreventDefault != PREVENT_DEFAULT_YES) { - mTouchMode = TOUCH_DONE_MODE; - performLongClick(); - } - break; - } - case RELEASE_SINGLE_TAP: { - doShortPress(); - break; - } case SCROLL_TO_MSG_ID: { // arg1 = animate, arg2 = onlyIfImeIsShowing // obj = Point(x, y) @@ -8207,6 +7468,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc if (mIsPaused) { nativeSetPauseDrawing(mNativeClass, true); } + mInputDispatcher = new WebViewInputDispatcher(this, + mWebViewCore.getInputDispatcherCallbacks()); break; case UPDATE_TEXTFIELD_TEXT_MSG_ID: // Make sure that the textfield is currently focused @@ -8263,20 +7526,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc break; case WEBCORE_NEED_TOUCH_EVENTS: - mForwardTouchEvents = (msg.arg1 != 0); - break; - - case PREVENT_TOUCH_ID: - if (inFullScreenMode()) { - break; - } - TouchEventData ted = (TouchEventData) msg.obj; - - if (mTouchEventQueue.enqueueTouchEvent(ted)) { - // WebCore is responding to us; remove pending timeout. - // It will be re-posted when needed. - removeMessages(PREVENT_DEFAULT_TIMEOUT); - } + mInputDispatcher.setWebKitWantsTouchEvents(msg.arg1 != 0); break; case REQUEST_KEYBOARD: @@ -8456,10 +7706,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc mFieldPointer = initData.mFieldPointer; mInputConnection.initEditorInfo(initData); mInputConnection.setTextAndKeepSelection(initData.mText); - mEditTextBounds.set(initData.mNodeBounds); + mEditTextContentBounds.set(initData.mContentBounds); mEditTextLayerId = initData.mNodeLayerId; nativeMapLayerRect(mNativeClass, mEditTextLayerId, - mEditTextBounds); + mEditTextContentBounds); mEditTextContent.set(initData.mContentRect); relocateAutoCompletePopup(); } @@ -8476,13 +7726,27 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } case UPDATE_MATCH_COUNT: { - boolean isNewFind = mLastFind == null || !mLastFind.equals(msg.obj); - if (mFindCallback != null) - mFindCallback.updateMatchCount(msg.arg1, msg.arg2, isNewFind); - if (mFindListener != null) - mFindListener.onFindResultReceived(msg.arg1, msg.arg2, true); + WebViewCore.FindAllRequest request = (WebViewCore.FindAllRequest)msg.obj; + if (request == null) { + if (mFindCallback != null) { + mFindCallback.updateMatchCount(0, 0, true); + } + } else if (request == mFindRequest) { + int matchCount, matchIndex; + synchronized (mFindRequest) { + matchCount = request.mMatchCount; + matchIndex = request.mMatchIndex; + } + if (mFindCallback != null) { + mFindCallback.updateMatchCount(matchIndex, matchCount, false); + } + if (mFindListener != null) { + mFindListener.onFindResultReceived(matchIndex, matchCount, true); + } + } break; } + case CLEAR_CARET_HANDLE: selectionDone(); break; @@ -8500,10 +7764,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc msg.arg1, /* unused */0); break; - case ANIMATE_TEXT_SCROLL: - computeEditTextScroll(); - break; - case EDIT_TEXT_SIZE_CHANGED: if (msg.arg1 == mFieldPointer) { mEditTextContent.set((Rect)msg.obj); @@ -8518,11 +7778,34 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc } break; + case UPDATE_CONTENT_BOUNDS: + mEditTextContentBounds.set((Rect) msg.obj); + break; + + case SCROLL_EDIT_TEXT: + scrollEditWithCursor(); + break; + default: super.handleMessage(msg); break; } } + + @Override + public Looper getUiLooper() { + return getLooper(); + } + + @Override + public void dispatchUiEvent(MotionEvent event, int eventType, int flags) { + onHandleUiEvent(event, eventType, flags); + } + + @Override + public Context getContext() { + return WebViewClassic.this.getContext(); + } } private void setHitTestTypeFromUrl(String url) { @@ -8585,13 +7868,16 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc if (mFocusedNode.mHasFocus && mFocusedNode.mEditable) { return false; } - long delay = System.currentTimeMillis() - mTouchHighlightRequested; + long delay = SystemClock.uptimeMillis() - mTouchHighlightRequested; if (delay < ViewConfiguration.getTapTimeout()) { Rect r = mTouchHighlightRegion.getBounds(); mWebView.postInvalidateDelayed(delay, r.left, r.top, r.right, r.bottom); return false; } - return true; + if (mInputDispatcher == null) { + return false; + } + return mInputDispatcher.shouldShowTapHighlight(); } @@ -8701,8 +7987,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc if (viewRect.width() < getWidth() >> 1 || viewRect.height() < getHeight() >> 1) { mTouchHighlightRegion.union(viewRect); - } else { - Log.w(LOGTAG, "Skip the huge selection rect:" + } else if (DebugFlags.WEB_VIEW) { + Log.d(LOGTAG, "Skip the huge selection rect:" + viewRect); } } @@ -8813,6 +8099,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc if (isPictureAfterFirstLayout) { mViewManager.postReadyToDrawAll(); } + scrollEditWithCursor(); } /** @@ -8855,13 +8142,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc invalidate(); } - private void computeEditTextScroll() { - if (mEditTextScroller.computeScrollOffset()) { - scrollEditText(mEditTextScroller.getCurrX(), - mEditTextScroller.getCurrY()); - } - } - private void scrollEditText(int scrollX, int scrollY) { // Scrollable edit text. Scroll it. float maxScrollX = getMaxTextScrollX(); @@ -8869,8 +8149,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc mEditTextContent.offsetTo(-scrollX, -scrollY); mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SCROLL_TEXT_INPUT, 0, scrollY, (Float)scrollPercentX); - mPrivateHandler.sendEmptyMessageDelayed(ANIMATE_TEXT_SCROLL, - TEXT_SCROLL_ANIMATION_DELAY_MS); } private void beginTextBatch() { @@ -9404,13 +8682,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc && mWebView.getLayerType() != View.LAYER_TYPE_SOFTWARE) { hwAccelerated = true; } + + // result is of type LayerAndroid::InvalidateFlags, non zero means invalidate/redraw int result = nativeSetHwAccelerated(mNativeClass, hwAccelerated); - if (mWebViewCore == null || mBlockWebkitViewMessages) { - return; - } - if (result == 1) { - // Sync layers - mWebViewCore.layersDraw(); + if (mWebViewCore != null && !mBlockWebkitViewMessages && result != 0) { + mWebViewCore.contentDraw(); } } diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index b4ebc09..15a2d48 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -40,6 +40,7 @@ import android.view.MotionEvent; import android.view.SurfaceView; import android.view.View; import android.webkit.WebViewClassic.FocusNodeHref; +import android.webkit.WebViewInputDispatcher.WebKitCallbacks; import junit.framework.Assert; @@ -259,6 +260,10 @@ public final class WebViewCore { return mBrowserFrame; } + public WebKitCallbacks getInputDispatcherCallbacks() { + return mEventHub; + } + //------------------------------------------------------------------------- // Common methods //------------------------------------------------------------------------- @@ -595,11 +600,6 @@ public final class WebViewCore { Point wh); /** - * Update the layers' content - */ - private native boolean nativeUpdateLayers(int nativeClass, int baseLayer); - - /** * Notify webkit that animations have begun (on the hardware accelerated content) */ private native void nativeNotifyAnimationStarted(int nativeClass); @@ -616,9 +616,6 @@ public final class WebViewCore { int unichar, int repeatCount, boolean isShift, boolean isAlt, boolean isSym, boolean isDown); - private native void nativeClick(int nativeClass, int framePtr, int nodePtr, - boolean fake); - private native void nativeSendListBoxChoices(int nativeClass, boolean[] choices, int size); @@ -661,8 +658,7 @@ public final class WebViewCore { int x, int y); private native String nativeRetrieveImageSource(int nativeClass, int x, int y); - private native void nativeTouchUp(int nativeClass, - int touchGeneration, int framePtr, int nodePtr, int x, int y); + private native boolean nativeMouseClick(int nativeClass); private native boolean nativeHandleTouchEvent(int nativeClass, int action, int[] idArray, int[] xArray, int[] yArray, int count, @@ -949,7 +945,7 @@ public final class WebViewCore { public String mName; public String mLabel; public int mMaxLength; - public Rect mNodeBounds; + public Rect mContentBounds; public int mNodeLayerId; public Rect mContentRect; } @@ -1025,8 +1021,8 @@ public final class WebViewCore { "REQUEST_CURSOR_HREF", // = 137; "ADD_JS_INTERFACE", // = 138; "LOAD_DATA", // = 139; - "TOUCH_UP", // = 140; - "TOUCH_EVENT", // = 141; + "", // = 140; + "", // = 141; "SET_ACTIVE", // = 142; "ON_PAUSE", // = 143 "ON_RESUME", // = 144 @@ -1041,15 +1037,17 @@ public final class WebViewCore { public FindAllRequest(String text) { mSearchText = text; mMatchCount = -1; + mMatchIndex = -1; } - public String mSearchText; + public final String mSearchText; public int mMatchCount; + public int mMatchIndex; } /** * @hide */ - public class EventHub { + public class EventHub implements WebViewInputDispatcher.WebKitCallbacks { // Message Ids static final int REVEAL_SELECTION = 96; static final int SCROLL_TEXT_INPUT = 99; @@ -1070,10 +1068,8 @@ public final class WebViewCore { static final int REPLACE_TEXT = 114; static final int PASS_TO_JS = 115; static final int SET_GLOBAL_BOUNDS = 116; - static final int CLICK = 118; static final int SET_NETWORK_STATE = 119; static final int DOC_HAS_IMAGES = 120; - static final int FAKE_CLICK = 121; static final int DELETE_SELECTION = 122; static final int LISTBOX_CHOICES = 123; static final int SINGLE_LISTBOX_CHOICE = 124; @@ -1094,11 +1090,6 @@ public final class WebViewCore { static final int ADD_JS_INTERFACE = 138; static final int LOAD_DATA = 139; - // motion - static final int TOUCH_UP = 140; - // message used to pass UI touch events to WebCore - static final int TOUCH_EVENT = 141; - // Used to tell the focus controller not to draw the blinking cursor, // based on whether the WebView has focus and whether the WebView's // cursor matches the webpage's focus. @@ -1113,9 +1104,6 @@ public final class WebViewCore { // Load and save web archives static final int SAVE_WEBARCHIVE = 147; - // Update layers - static final int WEBKIT_DRAW_LAYERS = 148; - static final int REMOVE_JS_INTERFACE = 149; // Network-based messaging @@ -1150,7 +1138,7 @@ public final class WebViewCore { // accessibility support static final int MODIFY_SELECTION = 190; - static final int USE_MOCK_DEVICE_ORIENTATION = 191; + static final int SET_USE_MOCK_DEVICE_ORIENTATION = 191; static final int AUTOFILL_FORM = 192; @@ -1264,10 +1252,6 @@ public final class WebViewCore { webkitDraw(); break; - case WEBKIT_DRAW_LAYERS: - webkitDrawLayers(); - break; - case DESTROY: // Time to take down the world. Cancel all pending // loads and destroy the native view and frame. @@ -1297,7 +1281,13 @@ public final class WebViewCore { } else { xPercent = ((Float) msg.obj).floatValue(); } - nativeScrollFocusedTextInput(mNativeClass, xPercent, msg.arg2); + Rect contentBounds = new Rect(); + nativeScrollFocusedTextInput(mNativeClass, xPercent, + msg.arg2, contentBounds); + Message.obtain( + mWebViewClassic.mPrivateHandler, + WebViewClassic.UPDATE_CONTENT_BOUNDS, + contentBounds).sendToTarget(); break; case LOAD_URL: { @@ -1374,14 +1364,6 @@ public final class WebViewCore { keyPress(msg.arg1); break; - case FAKE_CLICK: - nativeClick(mNativeClass, msg.arg1, msg.arg2, true); - break; - - case CLICK: - nativeClick(mNativeClass, msg.arg1, msg.arg2, false); - break; - case VIEW_SIZE_CHANGED: { viewSizeChanged((WebViewClassic.ViewSizeData) msg.obj); break; @@ -1494,45 +1476,6 @@ public final class WebViewCore { nativeCloseIdleConnections(mNativeClass); break; - case TOUCH_UP: - TouchUpData touchUpData = (TouchUpData) msg.obj; - if (touchUpData.mNativeLayer != 0) { - nativeScrollLayer(mNativeClass, - touchUpData.mNativeLayer, - touchUpData.mNativeLayerRect); - } - nativeTouchUp(mNativeClass, - touchUpData.mMoveGeneration, - touchUpData.mFrame, touchUpData.mNode, - touchUpData.mX, touchUpData.mY); - break; - - case TOUCH_EVENT: { - TouchEventData ted = (TouchEventData) msg.obj; - final int count = ted.mPoints.length; - int[] xArray = new int[count]; - int[] yArray = new int[count]; - for (int c = 0; c < count; c++) { - xArray[c] = ted.mPoints[c].x; - yArray[c] = ted.mPoints[c].y; - } - if (ted.mNativeLayer != 0) { - nativeScrollLayer(mNativeClass, - ted.mNativeLayer, ted.mNativeLayerRect); - } - ted.mNativeResult = nativeHandleTouchEvent( - mNativeClass, ted.mAction, ted.mIds, xArray, - yArray, count, ted.mActionIndex, - ted.mMetaState); - Message.obtain( - mWebViewClassic.mPrivateHandler, - WebViewClassic.PREVENT_TOUCH_ID, - ted.mAction, - ted.mNativeResult ? 1 : 0, - ted).sendToTarget(); - break; - } - case SET_ACTIVE: nativeSetFocusControllerActive(mNativeClass, msg.arg1 == 1); break; @@ -1707,8 +1650,8 @@ public final class WebViewCore { .sendToTarget(); break; - case USE_MOCK_DEVICE_ORIENTATION: - useMockDeviceOrientation(); + case SET_USE_MOCK_DEVICE_ORIENTATION: + setUseMockDeviceOrientation(); break; case AUTOFILL_FORM: @@ -1777,21 +1720,32 @@ public final class WebViewCore { nativeSelectAll(mNativeClass); break; case FIND_ALL: { - FindAllRequest request = (FindAllRequest) msg.obj; - if (request == null) { - nativeFindAll(mNativeClass, null); - } else { - request.mMatchCount = nativeFindAll( - mNativeClass, request.mSearchText); - synchronized(request) { + FindAllRequest request = (FindAllRequest)msg.obj; + if (request != null) { + int matchCount = nativeFindAll(mNativeClass, request.mSearchText); + int matchIndex = nativeFindNext(mNativeClass, true); + synchronized (request) { + request.mMatchCount = matchCount; + request.mMatchIndex = matchIndex; request.notify(); } + } else { + nativeFindAll(mNativeClass, null); } + Message.obtain(mWebViewClassic.mPrivateHandler, + WebViewClassic.UPDATE_MATCH_COUNT, request).sendToTarget(); break; } - case FIND_NEXT: - nativeFindNext(mNativeClass, msg.arg1 != 0); + case FIND_NEXT: { + FindAllRequest request = (FindAllRequest)msg.obj; + int matchIndex = nativeFindNext(mNativeClass, msg.arg1 != 0); + synchronized (request) { + request.mMatchIndex = matchIndex; + } + Message.obtain(mWebViewClassic.mPrivateHandler, + WebViewClassic.UPDATE_MATCH_COUNT, request).sendToTarget(); break; + } } } }; @@ -1805,6 +1759,38 @@ public final class WebViewCore { } } + @Override + public Looper getWebKitLooper() { + return mHandler.getLooper(); + } + + @Override + public boolean dispatchWebKitEvent(MotionEvent event, int eventType, int flags) { + switch (eventType) { + case WebViewInputDispatcher.EVENT_TYPE_CLICK: + return nativeMouseClick(mNativeClass); + + case WebViewInputDispatcher.EVENT_TYPE_TOUCH: { + int count = event.getPointerCount(); + int[] idArray = new int[count]; + int[] xArray = new int[count]; + int[] yArray = new int[count]; + for (int i = 0; i < count; i++) { + idArray[i] = event.getPointerId(i); + xArray[i] = (int) event.getX(i); + yArray[i] = (int) event.getY(i); + } + return nativeHandleTouchEvent(mNativeClass, + event.getActionMasked(), + idArray, xArray, yArray, count, + event.getActionIndex(), event.getMetaState()); + } + + default: + return false; + } + } + /** * Send a message internally to the queue or to the handler */ @@ -2135,7 +2121,6 @@ public final class WebViewCore { // Used to avoid posting more than one draw message. private boolean mDrawIsScheduled; - private boolean mDrawLayersIsScheduled; // Used to avoid posting more than one split picture message. private boolean mSplitPictureIsScheduled; @@ -2181,25 +2166,6 @@ public final class WebViewCore { DrawData mLastDrawData = null; - // Only update the layers' content, not the base surface - // PictureSet. - private void webkitDrawLayers() { - mDrawLayersIsScheduled = false; - if (mDrawIsScheduled || mLastDrawData == null) { - removeMessages(EventHub.WEBKIT_DRAW); - webkitDraw(); - return; - } - // Directly update the layers we last passed to the UI side - if (nativeUpdateLayers(mNativeClass, mLastDrawData.mBaseLayer)) { - // If anything more complex than position has been touched, let's do a full draw - webkitDraw(); - } - mWebViewClassic.mPrivateHandler.removeMessages(WebViewClassic.INVAL_RECT_MSG_ID); - mWebViewClassic.mPrivateHandler.sendMessageAtFrontOfQueue(mWebViewClassic.mPrivateHandler - .obtainMessage(WebViewClassic.INVAL_RECT_MSG_ID)); - } - private Boolean m_skipDrawFlag = false; private boolean m_drawWasSkipped = false; @@ -2375,15 +2341,6 @@ public final class WebViewCore { } } - // called from JNI - void layersDraw() { - synchronized (this) { - if (mDrawLayersIsScheduled) return; - mDrawLayersIsScheduled = true; - mEventHub.sendMessage(Message.obtain(null, EventHub.WEBKIT_DRAW_LAYERS)); - } - } - // called by JNI private void contentScrollTo(int x, int y, boolean animate, boolean onlyIfImeIsShowing) { @@ -2825,17 +2782,6 @@ public final class WebViewCore { .sendToTarget(); } - // called by JNI - private void updateMatchCount(int matchIndex, int matchCount, - String findText) { - if (mWebViewClassic == null) { - return; - } - Message.obtain(mWebViewClassic.mPrivateHandler, - WebViewClassic.UPDATE_MATCH_COUNT, matchIndex, matchCount, - findText).sendToTarget(); - } - private native void nativeRevealSelection(int nativeClass); private native String nativeRequestLabel(int nativeClass, int framePtr, int nodePtr); @@ -2843,7 +2789,7 @@ public final class WebViewCore { * Scroll the focused textfield to (xPercent, y) in document space */ private native void nativeScrollFocusedTextInput(int nativeClass, - float xPercent, int y); + float xPercent, int y, Rect contentBounds); // these must be in document space (i.e. not scaled/zoomed). private native void nativeSetScrollOffset(int nativeClass, @@ -3047,8 +2993,8 @@ public final class WebViewCore { // TODO: Figure out what to do with this (b/6111818) } - private void useMockDeviceOrientation() { - mDeviceMotionAndOrientationManager.useMock(); + private void setUseMockDeviceOrientation() { + mDeviceMotionAndOrientationManager.setUseMock(); } public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha, @@ -3086,7 +3032,7 @@ public final class WebViewCore { private native void nativeAutoFillForm(int nativeClass, int queryId); private native void nativeScrollLayer(int nativeClass, int layer, Rect rect); private native int nativeFindAll(int nativeClass, String text); - private native void nativeFindNext(int nativeClass, boolean forward); + private native int nativeFindNext(int nativeClass, boolean forward); /** * Deletes editable text between two points. Note that the selection may diff --git a/core/java/android/webkit/WebViewInputDispatcher.java b/core/java/android/webkit/WebViewInputDispatcher.java new file mode 100644 index 0000000..c8677ec --- /dev/null +++ b/core/java/android/webkit/WebViewInputDispatcher.java @@ -0,0 +1,1157 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.SystemClock; +import android.util.Log; +import android.view.InputDevice; +import android.view.MotionEvent; +import android.view.ViewConfiguration; + +/** + * Perform asynchronous dispatch of input events in a {@link WebView}. + * + * This dispatcher is shared by the UI thread ({@link WebViewClassic}) and web kit + * thread ({@link WebViewCore}). The UI thread enqueues events for + * processing, waits for the web kit thread to handle them, and then performs + * additional processing depending on the outcome. + * + * How it works: + * + * 1. The web view thread receives an input event from the input system on the UI + * thread in its {@link WebViewClassic#onTouchEvent} handler. It sends the input event + * to the dispatcher, then immediately returns true to the input system to indicate that + * it will handle the event. + * + * 2. The web kit thread is notified that an event has been enqueued. Meanwhile additional + * events may be enqueued from the UI thread. In some cases, the dispatcher may decide to + * coalesce motion events into larger batches or to cancel events that have been + * sitting in the queue for too long. + * + * 3. The web kit thread wakes up and handles all input events that are waiting for it. + * After processing each input event, it informs the dispatcher whether the web application + * has decided to handle the event itself and to prevent default event handling. + * + * 4. If web kit indicates that it wants to prevent default event handling, then web kit + * consumes the remainder of the gesture and web view receives a cancel event if + * needed. Otherwise, the web view handles the gesture on the UI thread normally. + * + * 5. If the web kit thread takes too long to handle an input event, then it loses the + * right to handle it. The dispatcher synthesizes a cancellation event for web kit and + * then tells the web view on the UI thread to handle the event that timed out along + * with the rest of the gesture. + * + * One thing to keep in mind about the dispatcher is that what goes into the dispatcher + * is not necessarily what the web kit or UI thread will see. As mentioned above, the + * dispatcher may tweak the input event stream to improve responsiveness. Both web view and + * web kit are guaranteed to perceive a consistent stream of input events but + * they might not always see the same events (especially if one decides + * to prevent the other from handling a particular gesture). + * + * This implementation very deliberately does not refer to the {@link WebViewClassic} + * or {@link WebViewCore} classes, preferring to communicate with them only via + * interfaces to avoid unintentional coupling to their implementation details. + * + * Currently, the input dispatcher only handles pointer events (includes touch, + * hover and scroll events). In principle, it could be extended to handle trackball + * and key events if needed. + * + * @hide + */ +final class WebViewInputDispatcher { + private static final String TAG = "WebViewInputDispatcher"; + private static final boolean DEBUG = false; + // This enables batching of MotionEvents. It will combine multiple MotionEvents + // together into a single MotionEvent if more events come in while we are + // still waiting on the processing of a previous event. + // If this is set to false, we will instead opt to drop ACTION_MOVE + // events we cannot keep up with. + // TODO: If batching proves to be working well, remove this + private static final boolean ENABLE_EVENT_BATCHING = true; + + private final Object mLock = new Object(); + + // Pool of queued input events. (guarded by mLock) + private static final int MAX_DISPATCH_EVENT_POOL_SIZE = 10; + private DispatchEvent mDispatchEventPool; + private int mDispatchEventPoolSize; + + // Posted state, tracks events posted to the dispatcher. (guarded by mLock) + private final TouchStream mPostTouchStream = new TouchStream(); + private boolean mPostSendTouchEventsToWebKit; + private boolean mPostDoNotSendTouchEventsToWebKitUntilNextGesture; + private boolean mPostLongPressScheduled; + private boolean mPostClickScheduled; + private int mPostLastWebKitXOffset; + private int mPostLastWebKitYOffset; + private float mPostLastWebKitScale; + + // State for event tracking (click, longpress, double tap, etc..) + private boolean mIsDoubleTapCandidate; + private boolean mIsTapCandidate; + private float mInitialDownX; + private float mInitialDownY; + private float mTouchSlopSquared; + private float mDoubleTapSlopSquared; + + // Web kit state, tracks events observed by web kit. (guarded by mLock) + private final DispatchEventQueue mWebKitDispatchEventQueue = new DispatchEventQueue(); + private final TouchStream mWebKitTouchStream = new TouchStream(); + private final WebKitCallbacks mWebKitCallbacks; + private final WebKitHandler mWebKitHandler; + private boolean mWebKitDispatchScheduled; + private boolean mWebKitTimeoutScheduled; + private long mWebKitTimeoutTime; + + // UI state, tracks events observed by the UI. (guarded by mLock) + private final DispatchEventQueue mUiDispatchEventQueue = new DispatchEventQueue(); + private final TouchStream mUiTouchStream = new TouchStream(); + private final UiCallbacks mUiCallbacks; + private final UiHandler mUiHandler; + private boolean mUiDispatchScheduled; + + // Give up on web kit handling of input events when this timeout expires. + private static final long WEBKIT_TIMEOUT_MILLIS = 200; + private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); + private static final int LONG_PRESS_TIMEOUT = + ViewConfiguration.getLongPressTimeout() + TAP_TIMEOUT; + private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); + + /** + * Event type: Indicates a touch event type. + * + * This event is delivered together with a {@link MotionEvent} with one of the + * following actions: {@link MotionEvent#ACTION_DOWN}, {@link MotionEvent#ACTION_MOVE}, + * {@link MotionEvent#ACTION_UP}, {@link MotionEvent#ACTION_POINTER_DOWN}, + * {@link MotionEvent#ACTION_POINTER_UP}, {@link MotionEvent#ACTION_CANCEL}. + */ + public static final int EVENT_TYPE_TOUCH = 0; + + /** + * Event type: Indicates a hover event type. + * + * This event is delivered together with a {@link MotionEvent} with one of the + * following actions: {@link MotionEvent#ACTION_HOVER_ENTER}, + * {@link MotionEvent#ACTION_HOVER_MOVE}, {@link MotionEvent#ACTION_HOVER_MOVE}. + */ + public static final int EVENT_TYPE_HOVER = 1; + + /** + * Event type: Indicates a scroll event type. + * + * This event is delivered together with a {@link MotionEvent} with action + * {@link MotionEvent#ACTION_SCROLL}. + */ + public static final int EVENT_TYPE_SCROLL = 2; + + /** + * Event type: Indicates a long-press event type. + * + * This event is delivered in the middle of a sequence of {@link #EVENT_TYPE_TOUCH} events. + * It includes a {@link MotionEvent} with action {@link MotionEvent#ACTION_MOVE} + * that indicates the current touch coordinates of the long-press. + * + * This event is sent when the current touch gesture has been held longer than + * the long-press interval. + */ + public static final int EVENT_TYPE_LONG_PRESS = 3; + + /** + * Event type: Indicates a click event type. + * + * This event is delivered after a sequence of {@link #EVENT_TYPE_TOUCH} events that + * comprise a complete gesture ending with {@link MotionEvent#ACTION_UP}. + * It includes a {@link MotionEvent} with action {@link MotionEvent#ACTION_UP} + * that indicates the location of the click. + * + * This event is sent shortly after the end of a touch after the double-tap + * interval has expired to indicate a click. + */ + public static final int EVENT_TYPE_CLICK = 4; + + /** + * Event type: Indicates a double-tap event type. + * + * This event is delivered after a sequence of {@link #EVENT_TYPE_TOUCH} events that + * comprise a complete gesture ending with {@link MotionEvent#ACTION_UP}. + * It includes a {@link MotionEvent} with action {@link MotionEvent#ACTION_UP} + * that indicates the location of the double-tap. + * + * This event is sent immediately after a sequence of two touches separated + * in time by no more than the double-tap interval and separated in space + * by no more than the double-tap slop. + */ + public static final int EVENT_TYPE_DOUBLE_TAP = 5; + + /** + * Flag: This event is private to this queue. Do not forward it. + */ + public static final int FLAG_PRIVATE = 1 << 0; + + /** + * Flag: This event is currently being processed by web kit. + * If a timeout occurs, make a copy of it before forwarding the event to another queue. + */ + public static final int FLAG_WEBKIT_IN_PROGRESS = 1 << 1; + + /** + * Flag: A timeout occurred while waiting for web kit to process this input event. + */ + public static final int FLAG_WEBKIT_TIMEOUT = 1 << 2; + + /** + * Flag: Indicates that the event was transformed for delivery to web kit. + * The event must be transformed back before being delivered to the UI. + */ + public static final int FLAG_WEBKIT_TRANSFORMED_EVENT = 1 << 3; + + public WebViewInputDispatcher(UiCallbacks uiCallbacks, WebKitCallbacks webKitCallbacks) { + this.mUiCallbacks = uiCallbacks; + mUiHandler = new UiHandler(uiCallbacks.getUiLooper()); + + this.mWebKitCallbacks = webKitCallbacks; + mWebKitHandler = new WebKitHandler(webKitCallbacks.getWebKitLooper()); + + ViewConfiguration config = ViewConfiguration.get(mUiCallbacks.getContext()); + mDoubleTapSlopSquared = config.getScaledDoubleTapSlop(); + mDoubleTapSlopSquared = (mDoubleTapSlopSquared * mDoubleTapSlopSquared); + mTouchSlopSquared = config.getScaledTouchSlop(); + mTouchSlopSquared = (mTouchSlopSquared * mTouchSlopSquared); + } + + /** + * Sets whether web kit wants to receive touch events. + * + * @param enable True to enable dispatching of touch events to web kit, otherwise + * web kit will be skipped. + */ + public void setWebKitWantsTouchEvents(boolean enable) { + if (DEBUG) { + Log.d(TAG, "webkitWantsTouchEvents: " + enable); + } + synchronized (mLock) { + if (mPostSendTouchEventsToWebKit != enable) { + if (!enable) { + enqueueWebKitCancelTouchEventIfNeededLocked(); + } + mPostSendTouchEventsToWebKit = enable; + } + } + } + + /** + * Posts a pointer event to the dispatch queue. + * + * @param event The event to post. + * @param webKitXOffset X offset to apply to events before dispatching them to web kit. + * @param webKitYOffset Y offset to apply to events before dispatching them to web kit. + * @param webKitScale The scale factor to apply to translated events before dispatching + * them to web kit. + * @return True if the dispatcher will handle the event, false if the event is unsupported. + */ + public boolean postPointerEvent(MotionEvent event, + int webKitXOffset, int webKitYOffset, float webKitScale) { + if (event == null + || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { + throw new IllegalArgumentException("event must be a pointer event"); + } + + if (DEBUG) { + Log.d(TAG, "postPointerEvent: " + event); + } + + final int action = event.getActionMasked(); + final int eventType; + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_POINTER_UP: + case MotionEvent.ACTION_CANCEL: + eventType = EVENT_TYPE_TOUCH; + break; + case MotionEvent.ACTION_SCROLL: + eventType = EVENT_TYPE_SCROLL; + break; + case MotionEvent.ACTION_HOVER_ENTER: + case MotionEvent.ACTION_HOVER_MOVE: + case MotionEvent.ACTION_HOVER_EXIT: + eventType = EVENT_TYPE_HOVER; + break; + default: + return false; // currently unsupported event type + } + + synchronized (mLock) { + // Ensure that the event is consistent and should be delivered. + MotionEvent eventToEnqueue = event; + if (eventType == EVENT_TYPE_TOUCH) { + eventToEnqueue = mPostTouchStream.update(event); + if (eventToEnqueue == null) { + if (DEBUG) { + Log.d(TAG, "postPointerEvent: dropped event " + event); + } + unscheduleLongPressLocked(); + unscheduleClickLocked(); + return false; + } + + if (mPostSendTouchEventsToWebKit + && mPostDoNotSendTouchEventsToWebKitUntilNextGesture + && action == MotionEvent.ACTION_DOWN) { + // Recover from a previous web kit timeout. + mPostDoNotSendTouchEventsToWebKitUntilNextGesture = false; + } + } + + // Copy the event because we need to retain ownership. + if (eventToEnqueue == event) { + eventToEnqueue = event.copy(); + } + + DispatchEvent d = obtainDispatchEventLocked(eventToEnqueue, eventType, 0, + webKitXOffset, webKitYOffset, webKitScale); + enqueueEventLocked(d); + } + return true; + } + + private void scheduleLongPressLocked() { + unscheduleLongPressLocked(); + mPostLongPressScheduled = true; + mUiHandler.sendEmptyMessageDelayed(UiHandler.MSG_LONG_PRESS, + LONG_PRESS_TIMEOUT); + } + + private void unscheduleLongPressLocked() { + if (mPostLongPressScheduled) { + mPostLongPressScheduled = false; + mUiHandler.removeMessages(UiHandler.MSG_LONG_PRESS); + } + } + + public boolean shouldShowTapHighlight() { + synchronized (mLock) { + return mPostLongPressScheduled || mPostClickScheduled; + } + } + + private void postLongPress() { + synchronized (mLock) { + if (!mPostLongPressScheduled) { + return; + } + mPostLongPressScheduled = false; + + MotionEvent event = mPostTouchStream.getLastEvent(); + if (event == null) { + return; + } + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_POINTER_UP: + break; + default: + return; + } + + MotionEvent eventToEnqueue = MotionEvent.obtainNoHistory(event); + eventToEnqueue.setAction(MotionEvent.ACTION_MOVE); + DispatchEvent d = obtainDispatchEventLocked(eventToEnqueue, EVENT_TYPE_LONG_PRESS, 0, + mPostLastWebKitXOffset, mPostLastWebKitYOffset, mPostLastWebKitScale); + enqueueEventLocked(d); + } + } + + private void scheduleClickLocked() { + unscheduleClickLocked(); + mPostClickScheduled = true; + mUiHandler.sendEmptyMessageDelayed(UiHandler.MSG_CLICK, DOUBLE_TAP_TIMEOUT); + } + + private void unscheduleClickLocked() { + if (mPostClickScheduled) { + mPostClickScheduled = false; + mUiHandler.removeMessages(UiHandler.MSG_CLICK); + } + } + + private void postClick() { + synchronized (mLock) { + if (!mPostClickScheduled) { + return; + } + mPostClickScheduled = false; + + MotionEvent event = mPostTouchStream.getLastEvent(); + if (event == null || event.getAction() != MotionEvent.ACTION_UP) { + return; + } + + MotionEvent eventToEnqueue = MotionEvent.obtainNoHistory(event); + DispatchEvent d = obtainDispatchEventLocked(eventToEnqueue, EVENT_TYPE_CLICK, 0, + mPostLastWebKitXOffset, mPostLastWebKitYOffset, mPostLastWebKitScale); + enqueueEventLocked(d); + } + } + + private void checkForDoubleTapOnDownLocked(MotionEvent event) { + mIsDoubleTapCandidate = false; + if (!mPostClickScheduled) { + return; + } + int deltaX = (int) mInitialDownX - (int) event.getX(); + int deltaY = (int) mInitialDownY - (int) event.getY(); + if ((deltaX * deltaX + deltaY * deltaY) < mDoubleTapSlopSquared) { + unscheduleClickLocked(); + mIsDoubleTapCandidate = true; + } + } + + private boolean isClickCandidateLocked(MotionEvent event) { + if (event == null + || event.getActionMasked() != MotionEvent.ACTION_UP + || !mIsTapCandidate) { + return false; + } + long downDuration = event.getEventTime() - event.getDownTime(); + return downDuration < TAP_TIMEOUT; + } + + private void enqueueDoubleTapLocked(MotionEvent event) { + unscheduleClickLocked(); + MotionEvent eventToEnqueue = MotionEvent.obtainNoHistory(event); + DispatchEvent d = obtainDispatchEventLocked(eventToEnqueue, EVENT_TYPE_DOUBLE_TAP, 0, + mPostLastWebKitXOffset, mPostLastWebKitYOffset, mPostLastWebKitScale); + enqueueEventLocked(d); + mIsDoubleTapCandidate = false; + } + + private void checkForSlopLocked(MotionEvent event) { + if (!mIsTapCandidate) { + return; + } + int deltaX = (int) mInitialDownX - (int) event.getX(); + int deltaY = (int) mInitialDownY - (int) event.getY(); + if ((deltaX * deltaX + deltaY * deltaY) > mTouchSlopSquared) { + unscheduleLongPressLocked(); + mIsTapCandidate = false; + } + } + + private void updateStateTrackersLocked(DispatchEvent d, MotionEvent event) { + mPostLastWebKitXOffset = d.mWebKitXOffset; + mPostLastWebKitYOffset = d.mWebKitYOffset; + mPostLastWebKitScale = d.mWebKitScale; + int action = event != null ? event.getAction() : MotionEvent.ACTION_CANCEL; + if (d.mEventType != EVENT_TYPE_TOUCH) { + return; + } + + if (action == MotionEvent.ACTION_CANCEL + || event.getPointerCount() > 1) { + unscheduleLongPressLocked(); + unscheduleClickLocked(); + mIsDoubleTapCandidate = false; + mIsTapCandidate = false; + } else if (action == MotionEvent.ACTION_DOWN) { + checkForDoubleTapOnDownLocked(event); + scheduleLongPressLocked(); + mIsTapCandidate = true; + mInitialDownX = event.getX(); + mInitialDownY = event.getY(); + } else if (action == MotionEvent.ACTION_UP) { + unscheduleLongPressLocked(); + if (isClickCandidateLocked(event)) { + if (mIsDoubleTapCandidate) { + enqueueDoubleTapLocked(event); + } else { + scheduleClickLocked(); + } + } + } else if (action == MotionEvent.ACTION_MOVE) { + checkForSlopLocked(event); + } + } + + /** + * Dispatches pending web kit events. + * Must only be called from the web kit thread. + * + * This method may be used to flush the queue of pending input events + * immediately. This method may help to reduce input dispatch latency + * if called before certain expensive operations such as drawing. + */ + public void dispatchWebKitEvents() { + dispatchWebKitEvents(false); + } + + private void dispatchWebKitEvents(boolean calledFromHandler) { + for (;;) { + // Get the next event, but leave it in the queue so we can move it to the UI + // queue if a timeout occurs. + DispatchEvent d; + MotionEvent event; + final int eventType; + int flags; + synchronized (mLock) { + if (!ENABLE_EVENT_BATCHING) { + drainStaleWebKitEventsLocked(); + } + d = mWebKitDispatchEventQueue.mHead; + if (d == null) { + if (mWebKitDispatchScheduled) { + mWebKitDispatchScheduled = false; + if (!calledFromHandler) { + mWebKitHandler.removeMessages( + WebKitHandler.MSG_DISPATCH_WEBKIT_EVENTS); + } + } + return; + } + + event = d.mEvent; + if (event != null) { + event.offsetLocation(d.mWebKitXOffset, d.mWebKitYOffset); + event.scale(d.mWebKitScale); + d.mFlags |= FLAG_WEBKIT_TRANSFORMED_EVENT; + } + + eventType = d.mEventType; + if (eventType == EVENT_TYPE_TOUCH) { + event = mWebKitTouchStream.update(event); + if (DEBUG && event == null && d.mEvent != null) { + Log.d(TAG, "dispatchWebKitEvents: dropped event " + d.mEvent); + } + } + + d.mFlags |= FLAG_WEBKIT_IN_PROGRESS; + flags = d.mFlags; + } + + // Handle the event. + final boolean preventDefault; + if (event == null) { + preventDefault = false; + } else { + preventDefault = dispatchWebKitEvent(event, eventType, flags); + } + + synchronized (mLock) { + flags = d.mFlags; + d.mFlags = flags & ~FLAG_WEBKIT_IN_PROGRESS; + boolean recycleEvent = event != d.mEvent; + + if ((flags & FLAG_WEBKIT_TIMEOUT) != 0) { + // A timeout occurred! + recycleDispatchEventLocked(d); + } else { + // Web kit finished in a timely manner. Dequeue the event. + assert mWebKitDispatchEventQueue.mHead == d; + mWebKitDispatchEventQueue.dequeue(); + + updateWebKitTimeoutLocked(); + + if ((flags & FLAG_PRIVATE) != 0) { + // Event was intended for web kit only. All done. + recycleDispatchEventLocked(d); + } else if (preventDefault) { + // Web kit has decided to consume the event! + if (d.mEventType == EVENT_TYPE_TOUCH) { + enqueueUiCancelTouchEventIfNeededLocked(); + } + } else { + // Web kit is being friendly. Pass the event to the UI. + enqueueUiEventUnbatchedLocked(d); + } + } + + if (event != null && recycleEvent) { + event.recycle(); + } + } + } + } + + // Runs on web kit thread. + private boolean dispatchWebKitEvent(MotionEvent event, int eventType, int flags) { + if (DEBUG) { + Log.d(TAG, "dispatchWebKitEvent: event=" + event + + ", eventType=" + eventType + ", flags=" + flags); + } + boolean preventDefault = mWebKitCallbacks.dispatchWebKitEvent( + event, eventType, flags); + if (DEBUG) { + Log.d(TAG, "dispatchWebKitEvent: preventDefault=" + preventDefault); + } + return preventDefault; + } + + private boolean isMoveEventLocked(DispatchEvent d) { + return d.mEvent != null + && d.mEvent.getActionMasked() == MotionEvent.ACTION_MOVE; + } + + private void drainStaleWebKitEventsLocked() { + DispatchEvent d = mWebKitDispatchEventQueue.mHead; + while (d != null && d.mNext != null + && isMoveEventLocked(d) + && isMoveEventLocked(d.mNext)) { + DispatchEvent next = d.mNext; + skipWebKitEventLocked(d); + d = next; + } + mWebKitDispatchEventQueue.mHead = d; + } + + // Runs on UI thread in response to the web kit thread appearing to be unresponsive. + private void handleWebKitTimeout() { + synchronized (mLock) { + if (!mWebKitTimeoutScheduled) { + return; + } + mWebKitTimeoutScheduled = false; + + if (DEBUG) { + Log.d(TAG, "handleWebKitTimeout: timeout occurred!"); + } + + // Drain the web kit event queue. + DispatchEvent d = mWebKitDispatchEventQueue.dequeueList(); + + // If web kit was processing an event (must be at the head of the list because + // it can only do one at a time), then clone it or ignore it. + if ((d.mFlags & FLAG_WEBKIT_IN_PROGRESS) != 0) { + d.mFlags |= FLAG_WEBKIT_TIMEOUT; + if ((d.mFlags & FLAG_PRIVATE) != 0) { + d = d.mNext; // the event is private to web kit, ignore it + } else { + d = copyDispatchEventLocked(d); + d.mFlags &= ~FLAG_WEBKIT_IN_PROGRESS; + } + } + + // Enqueue all non-private events for handling by the UI thread. + while (d != null) { + DispatchEvent next = d.mNext; + skipWebKitEventLocked(d); + d = next; + } + + // Tell web kit to cancel all pending touches. + // This also prevents us from sending web kit any more touches until the + // next gesture begins. (As required to ensure touch event stream consistency.) + enqueueWebKitCancelTouchEventIfNeededLocked(); + } + } + + private void skipWebKitEventLocked(DispatchEvent d) { + d.mNext = null; + if ((d.mFlags & FLAG_PRIVATE) != 0) { + recycleDispatchEventLocked(d); + } else { + d.mFlags |= FLAG_WEBKIT_TIMEOUT; + enqueueUiEventUnbatchedLocked(d); + } + } + + /** + * Dispatches pending UI events. + * Must only be called from the UI thread. + * + * This method may be used to flush the queue of pending input events + * immediately. This method may help to reduce input dispatch latency + * if called before certain expensive operations such as drawing. + */ + public void dispatchUiEvents() { + dispatchUiEvents(false); + } + + private void dispatchUiEvents(boolean calledFromHandler) { + for (;;) { + MotionEvent event; + final int eventType; + final int flags; + synchronized (mLock) { + DispatchEvent d = mUiDispatchEventQueue.dequeue(); + if (d == null) { + if (mUiDispatchScheduled) { + mUiDispatchScheduled = false; + if (!calledFromHandler) { + mUiHandler.removeMessages(UiHandler.MSG_DISPATCH_UI_EVENTS); + } + } + return; + } + + event = d.mEvent; + if (event != null && (d.mFlags & FLAG_WEBKIT_TRANSFORMED_EVENT) != 0) { + event.scale(1.0f / d.mWebKitScale); + event.offsetLocation(-d.mWebKitXOffset, -d.mWebKitYOffset); + d.mFlags &= ~FLAG_WEBKIT_TRANSFORMED_EVENT; + } + + eventType = d.mEventType; + if (eventType == EVENT_TYPE_TOUCH) { + event = mUiTouchStream.update(event); + if (DEBUG && event == null && d.mEvent != null) { + Log.d(TAG, "dispatchUiEvents: dropped event " + d.mEvent); + } + } + + flags = d.mFlags; + + updateStateTrackersLocked(d, event); + if (event == d.mEvent) { + d.mEvent = null; // retain ownership of event, don't recycle it yet + } + recycleDispatchEventLocked(d); + } + + // Handle the event. + if (event != null) { + dispatchUiEvent(event, eventType, flags); + event.recycle(); + } + } + } + + // Runs on UI thread. + private void dispatchUiEvent(MotionEvent event, int eventType, int flags) { + if (DEBUG) { + Log.d(TAG, "dispatchUiEvent: event=" + event + + ", eventType=" + eventType + ", flags=" + flags); + } + mUiCallbacks.dispatchUiEvent(event, eventType, flags); + } + + private void enqueueEventLocked(DispatchEvent d) { + if (!shouldSkipWebKit(d.mEventType)) { + enqueueWebKitEventLocked(d); + } else { + enqueueUiEventLocked(d); + } + } + + private boolean shouldSkipWebKit(int eventType) { + switch (eventType) { + case EVENT_TYPE_CLICK: + case EVENT_TYPE_HOVER: + case EVENT_TYPE_SCROLL: + return false; + case EVENT_TYPE_TOUCH: + return !mPostSendTouchEventsToWebKit + || mPostDoNotSendTouchEventsToWebKitUntilNextGesture; + } + return true; + } + + private void enqueueWebKitCancelTouchEventIfNeededLocked() { + // We want to cancel touch events that were delivered to web kit. + // Enqueue a null event at the end of the queue if needed. + if (mWebKitTouchStream.isCancelNeeded() || !mWebKitDispatchEventQueue.isEmpty()) { + DispatchEvent d = obtainDispatchEventLocked(null, EVENT_TYPE_TOUCH, FLAG_PRIVATE, + 0, 0, 1.0f); + enqueueWebKitEventUnbatchedLocked(d); + mPostDoNotSendTouchEventsToWebKitUntilNextGesture = true; + } + } + + private void enqueueWebKitEventLocked(DispatchEvent d) { + if (batchEventLocked(d, mWebKitDispatchEventQueue.mTail)) { + if (DEBUG) { + Log.d(TAG, "enqueueWebKitEventLocked: batched event " + d.mEvent); + } + recycleDispatchEventLocked(d); + } else { + enqueueWebKitEventUnbatchedLocked(d); + } + } + + private void enqueueWebKitEventUnbatchedLocked(DispatchEvent d) { + if (DEBUG) { + Log.d(TAG, "enqueueWebKitEventUnbatchedLocked: enqueued event " + d.mEvent); + } + mWebKitDispatchEventQueue.enqueue(d); + scheduleWebKitDispatchLocked(); + updateWebKitTimeoutLocked(); + } + + private void scheduleWebKitDispatchLocked() { + if (!mWebKitDispatchScheduled) { + mWebKitHandler.sendEmptyMessage(WebKitHandler.MSG_DISPATCH_WEBKIT_EVENTS); + mWebKitDispatchScheduled = true; + } + } + + private void updateWebKitTimeoutLocked() { + DispatchEvent d = mWebKitDispatchEventQueue.mHead; + if (d != null && mWebKitTimeoutScheduled && mWebKitTimeoutTime == d.mTimeoutTime) { + return; + } + if (mWebKitTimeoutScheduled) { + mUiHandler.removeMessages(UiHandler.MSG_WEBKIT_TIMEOUT); + mWebKitTimeoutScheduled = false; + } + if (d != null) { + mUiHandler.sendEmptyMessageAtTime(UiHandler.MSG_WEBKIT_TIMEOUT, d.mTimeoutTime); + mWebKitTimeoutScheduled = true; + mWebKitTimeoutTime = d.mTimeoutTime; + } + } + + private void enqueueUiCancelTouchEventIfNeededLocked() { + // We want to cancel touch events that were delivered to the UI. + // Enqueue a null event at the end of the queue if needed. + if (mUiTouchStream.isCancelNeeded() || !mUiDispatchEventQueue.isEmpty()) { + DispatchEvent d = obtainDispatchEventLocked(null, EVENT_TYPE_TOUCH, FLAG_PRIVATE, + 0, 0, 1.0f); + enqueueUiEventUnbatchedLocked(d); + } + } + + private void enqueueUiEventLocked(DispatchEvent d) { + if (batchEventLocked(d, mUiDispatchEventQueue.mTail)) { + if (DEBUG) { + Log.d(TAG, "enqueueUiEventLocked: batched event " + d.mEvent); + } + recycleDispatchEventLocked(d); + } else { + enqueueUiEventUnbatchedLocked(d); + } + } + + private void enqueueUiEventUnbatchedLocked(DispatchEvent d) { + if (DEBUG) { + Log.d(TAG, "enqueueUiEventUnbatchedLocked: enqueued event " + d.mEvent); + } + mUiDispatchEventQueue.enqueue(d); + scheduleUiDispatchLocked(); + } + + private void scheduleUiDispatchLocked() { + if (!mUiDispatchScheduled) { + mUiHandler.sendEmptyMessage(UiHandler.MSG_DISPATCH_UI_EVENTS); + mUiDispatchScheduled = true; + } + } + + private boolean batchEventLocked(DispatchEvent in, DispatchEvent tail) { + if (!ENABLE_EVENT_BATCHING) { + return false; + } + if (tail != null && tail.mEvent != null && in.mEvent != null + && in.mEventType == tail.mEventType + && in.mFlags == tail.mFlags + && in.mWebKitXOffset == tail.mWebKitXOffset + && in.mWebKitYOffset == tail.mWebKitYOffset + && in.mWebKitScale == tail.mWebKitScale) { + return tail.mEvent.addBatch(in.mEvent); + } + return false; + } + + private DispatchEvent obtainDispatchEventLocked(MotionEvent event, + int eventType, int flags, int webKitXOffset, int webKitYOffset, float webKitScale) { + DispatchEvent d = obtainUninitializedDispatchEventLocked(); + d.mEvent = event; + d.mEventType = eventType; + d.mFlags = flags; + d.mTimeoutTime = SystemClock.uptimeMillis() + WEBKIT_TIMEOUT_MILLIS; + d.mWebKitXOffset = webKitXOffset; + d.mWebKitYOffset = webKitYOffset; + d.mWebKitScale = webKitScale; + if (DEBUG) { + Log.d(TAG, "Timeout time: " + (d.mTimeoutTime - SystemClock.uptimeMillis())); + } + return d; + } + + private DispatchEvent copyDispatchEventLocked(DispatchEvent d) { + DispatchEvent copy = obtainUninitializedDispatchEventLocked(); + if (d.mEvent != null) { + copy.mEvent = d.mEvent.copy(); + } + copy.mEventType = d.mEventType; + copy.mFlags = d.mFlags; + copy.mTimeoutTime = d.mTimeoutTime; + copy.mWebKitXOffset = d.mWebKitXOffset; + copy.mWebKitYOffset = d.mWebKitYOffset; + copy.mWebKitScale = d.mWebKitScale; + copy.mNext = d.mNext; + return copy; + } + + private DispatchEvent obtainUninitializedDispatchEventLocked() { + DispatchEvent d = mDispatchEventPool; + if (d != null) { + mDispatchEventPoolSize -= 1; + mDispatchEventPool = d.mNext; + d.mNext = null; + } else { + d = new DispatchEvent(); + } + return d; + } + + private void recycleDispatchEventLocked(DispatchEvent d) { + if (d.mEvent != null) { + d.mEvent.recycle(); + d.mEvent = null; + } + + if (mDispatchEventPoolSize < MAX_DISPATCH_EVENT_POOL_SIZE) { + mDispatchEventPoolSize += 1; + d.mNext = mDispatchEventPool; + mDispatchEventPool = d; + } + } + + /* Implemented by {@link WebViewClassic} to perform operations on the UI thread. */ + public static interface UiCallbacks { + /** + * Gets the UI thread's looper. + * @return The looper. + */ + public Looper getUiLooper(); + + /** + * Gets the UI's context + * @return The context + */ + public Context getContext(); + + /** + * Dispatches an event to the UI. + * @param event The event. + * @param eventType The event type. + * @param flags The event's dispatch flags. + */ + public void dispatchUiEvent(MotionEvent event, int eventType, int flags); + } + + /* Implemented by {@link WebViewCore} to perform operations on the web kit thread. */ + public static interface WebKitCallbacks { + /** + * Gets the web kit thread's looper. + * @return The looper. + */ + public Looper getWebKitLooper(); + + /** + * Dispatches an event to web kit. + * @param event The event. + * @param eventType The event type. + * @param flags The event's dispatch flags. + * @return True if web kit wants to prevent default event handling. + */ + public boolean dispatchWebKitEvent(MotionEvent event, int eventType, int flags); + } + + // Runs on UI thread. + private final class UiHandler extends Handler { + public static final int MSG_DISPATCH_UI_EVENTS = 1; + public static final int MSG_WEBKIT_TIMEOUT = 2; + public static final int MSG_LONG_PRESS = 3; + public static final int MSG_CLICK = 4; + + public UiHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_DISPATCH_UI_EVENTS: + dispatchUiEvents(true); + break; + case MSG_WEBKIT_TIMEOUT: + handleWebKitTimeout(); + break; + case MSG_LONG_PRESS: + postLongPress(); + break; + case MSG_CLICK: + postClick(); + break; + default: + throw new IllegalStateException("Unknown message type: " + msg.what); + } + } + } + + // Runs on web kit thread. + private final class WebKitHandler extends Handler { + public static final int MSG_DISPATCH_WEBKIT_EVENTS = 1; + + public WebKitHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_DISPATCH_WEBKIT_EVENTS: + dispatchWebKitEvents(true); + break; + default: + throw new IllegalStateException("Unknown message type: " + msg.what); + } + } + } + + private static final class DispatchEvent { + public DispatchEvent mNext; + + public MotionEvent mEvent; + public int mEventType; + public int mFlags; + public long mTimeoutTime; + public int mWebKitXOffset; + public int mWebKitYOffset; + public float mWebKitScale; + } + + private static final class DispatchEventQueue { + public DispatchEvent mHead; + public DispatchEvent mTail; + + public boolean isEmpty() { + return mHead != null; + } + + public void enqueue(DispatchEvent d) { + if (mHead == null) { + mHead = d; + mTail = d; + } else { + mTail.mNext = d; + mTail = d; + } + } + + public DispatchEvent dequeue() { + DispatchEvent d = mHead; + if (d != null) { + DispatchEvent next = d.mNext; + if (next == null) { + mHead = null; + mTail = null; + } else { + mHead = next; + d.mNext = null; + } + } + return d; + } + + public DispatchEvent dequeueList() { + DispatchEvent d = mHead; + if (d != null) { + mHead = null; + mTail = null; + } + return d; + } + } + + /** + * Keeps track of a stream of touch events so that we can discard touch + * events that would make the stream inconsistent. + */ + private static final class TouchStream { + private MotionEvent mLastEvent; + + /** + * Gets the last touch event that was delivered. + * @return The last touch event, or null if none. + */ + public MotionEvent getLastEvent() { + return mLastEvent; + } + + /** + * Updates the touch event stream. + * @param event The event that we intend to send, or null to cancel the + * touch event stream. + * @return The event that we should actually send, or null if no event should + * be sent because the proposed event would make the stream inconsistent. + */ + public MotionEvent update(MotionEvent event) { + if (event == null) { + if (isCancelNeeded()) { + event = mLastEvent; + if (event != null) { + event.setAction(MotionEvent.ACTION_CANCEL); + mLastEvent = null; + } + } + return event; + } + + switch (event.getActionMasked()) { + case MotionEvent.ACTION_MOVE: + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_POINTER_UP: + if (mLastEvent == null + || mLastEvent.getAction() == MotionEvent.ACTION_UP) { + return null; + } + updateLastEvent(event); + return event; + + case MotionEvent.ACTION_DOWN: + updateLastEvent(event); + return event; + + case MotionEvent.ACTION_CANCEL: + if (mLastEvent == null) { + return null; + } + updateLastEvent(null); + return event; + + default: + return null; + } + } + + /** + * Returns true if there is a gesture in progress that may need to be canceled. + * @return True if cancel is needed. + */ + public boolean isCancelNeeded() { + return mLastEvent != null && mLastEvent.getAction() != MotionEvent.ACTION_UP; + } + + private void updateLastEvent(MotionEvent event) { + if (mLastEvent != null) { + mLastEvent.recycle(); + } + mLastEvent = event != null ? MotionEvent.obtainNoHistory(event) : null; + } + } +}
\ No newline at end of file diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java index e6184d5..b409e26 100755 --- a/core/java/android/widget/AppSecurityPermissions.java +++ b/core/java/android/widget/AppSecurityPermissions.java @@ -490,13 +490,7 @@ public class AppSecurityPermissions implements View.OnClickListener { // Development permissions are only shown to the user if they are already // granted to the app -- if we are installing an app and they are not // already granted, they will not be granted as part of the install. - // Note we also need the app to have specified this permission is not - // required -- this is not technically needed, but it helps various things - // if we ensure apps always mark development permissions as option, so that - // even not knowing what a permission is we can still know whether it will - // be granted to the app when it is installed. if ((existingReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0 - && (newReqFlags&PackageInfo.REQUESTED_PERMISSION_REQUIRED) == 0 && (pInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0) { return true; } diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java index 0685eea..858c415 100644 --- a/core/java/android/widget/CheckBox.java +++ b/core/java/android/widget/CheckBox.java @@ -21,8 +21,6 @@ import android.util.AttributeSet; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; -import com.android.internal.R; - /** * <p> @@ -71,16 +69,6 @@ public class CheckBox extends CompoundButton { } @Override - public void onPopulateAccessibilityEvent(AccessibilityEvent event) { - super.onPopulateAccessibilityEvent(event); - if (isChecked()) { - event.getText().add(mContext.getString(R.string.checkbox_checked)); - } else { - event.getText().add(mContext.getString(R.string.checkbox_not_checked)); - } - } - - @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setClassName(CheckBox.class.getName()); diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java index 9c9eb4b..b7a126e 100644 --- a/core/java/android/widget/Chronometer.java +++ b/core/java/android/widget/Chronometer.java @@ -248,7 +248,6 @@ public class Chronometer extends TextView { } } setText(text); - Slog.v("Chronometer", "updateText: sec=" + seconds + " mFormat=" + mFormat + " text=" + text); } private void updateRunning() { diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java index 4e13ea1..c2559a5 100644 --- a/core/java/android/widget/HorizontalScrollView.java +++ b/core/java/android/widget/HorizontalScrollView.java @@ -77,7 +77,7 @@ public class HorizontalScrollView extends FrameLayout { /** * Position of the last motion event. */ - private float mLastMotionX; + private int mLastMotionX; /** * True when the layout has changed but the traversal has not come through yet. @@ -460,7 +460,7 @@ public class HorizontalScrollView extends FrameLayout { } final int pointerIndex = ev.findPointerIndex(activePointerId); - final float x = ev.getX(pointerIndex); + final int x = (int) ev.getX(pointerIndex); final int xDiff = (int) Math.abs(x - mLastMotionX); if (xDiff > mTouchSlop) { mIsBeingDragged = true; @@ -473,7 +473,7 @@ public class HorizontalScrollView extends FrameLayout { } case MotionEvent.ACTION_DOWN: { - final float x = ev.getX(); + final int x = (int) ev.getX(); if (!inChild((int) x, (int) ev.getY())) { mIsBeingDragged = false; recycleVelocityTracker(); @@ -505,18 +505,18 @@ public class HorizontalScrollView extends FrameLayout { mIsBeingDragged = false; mActivePointerId = INVALID_POINTER; if (mScroller.springBack(mScrollX, mScrollY, 0, getScrollRange(), 0, 0)) { - invalidate(); + postInvalidateOnAnimation(); } break; case MotionEvent.ACTION_POINTER_DOWN: { final int index = ev.getActionIndex(); - mLastMotionX = ev.getX(index); + mLastMotionX = (int) ev.getX(index); mActivePointerId = ev.getPointerId(index); break; } case MotionEvent.ACTION_POINTER_UP: onSecondaryPointerUp(ev); - mLastMotionX = ev.getX(ev.findPointerIndex(mActivePointerId)); + mLastMotionX = (int) ev.getX(ev.findPointerIndex(mActivePointerId)); break; } @@ -550,7 +550,7 @@ public class HorizontalScrollView extends FrameLayout { } // Remember where the motion event started - mLastMotionX = ev.getX(); + mLastMotionX = (int) ev.getX(); mActivePointerId = ev.getPointerId(0); break; } @@ -558,7 +558,7 @@ public class HorizontalScrollView extends FrameLayout { if (mIsBeingDragged) { // Scroll to follow the motion event final int activePointerIndex = ev.findPointerIndex(mActivePointerId); - final float x = ev.getX(activePointerIndex); + final int x = (int) ev.getX(activePointerIndex); final int deltaX = (int) (mLastMotionX - x); mLastMotionX = x; @@ -591,7 +591,7 @@ public class HorizontalScrollView extends FrameLayout { } if (mEdgeGlowLeft != null && (!mEdgeGlowLeft.isFinished() || !mEdgeGlowRight.isFinished())) { - invalidate(); + postInvalidateOnAnimation(); } } } @@ -608,7 +608,7 @@ public class HorizontalScrollView extends FrameLayout { } else { if (mScroller.springBack(mScrollX, mScrollY, 0, getScrollRange(), 0, 0)) { - invalidate(); + postInvalidateOnAnimation(); } } } @@ -626,7 +626,7 @@ public class HorizontalScrollView extends FrameLayout { case MotionEvent.ACTION_CANCEL: if (mIsBeingDragged && getChildCount() > 0) { if (mScroller.springBack(mScrollX, mScrollY, 0, getScrollRange(), 0, 0)) { - invalidate(); + postInvalidateOnAnimation(); } mActivePointerId = INVALID_POINTER; mIsBeingDragged = false; @@ -654,7 +654,7 @@ public class HorizontalScrollView extends FrameLayout { // active pointer and adjust accordingly. // TODO: Make this decision more intelligent. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; - mLastMotionX = ev.getX(newPointerIndex); + mLastMotionX = (int) ev.getX(newPointerIndex); mActivePointerId = ev.getPointerId(newPointerIndex); if (mVelocityTracker != null) { mVelocityTracker.clear(); @@ -1084,7 +1084,7 @@ public class HorizontalScrollView extends FrameLayout { dx = Math.max(0, Math.min(scrollX + dx, maxX)) - scrollX; mScroller.startScroll(scrollX, mScrollY, dx, 0); - invalidate(); + postInvalidateOnAnimation(); } else { if (!mScroller.isFinished()) { mScroller.abortAnimation(); @@ -1206,7 +1206,7 @@ public class HorizontalScrollView extends FrameLayout { } if (!awakenScrollBars()) { - invalidate(); + postInvalidateOnAnimation(); } } } @@ -1452,7 +1452,7 @@ public class HorizontalScrollView extends FrameLayout { newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT); } - invalidate(); + postInvalidateOnAnimation(); } } @@ -1503,7 +1503,7 @@ public class HorizontalScrollView extends FrameLayout { canvas.translate(-height + mPaddingTop, Math.min(0, scrollX)); mEdgeGlowLeft.setSize(height, getWidth()); if (mEdgeGlowLeft.draw(canvas)) { - invalidate(); + postInvalidateOnAnimation(); } canvas.restoreToCount(restoreCount); } @@ -1517,7 +1517,7 @@ public class HorizontalScrollView extends FrameLayout { -(Math.max(getScrollRange(), scrollX) + width)); mEdgeGlowRight.setSize(height, width); if (mEdgeGlowRight.draw(canvas)) { - invalidate(); + postInvalidateOnAnimation(); } canvas.restoreToCount(restoreCount); } diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index d897a39..b2321d9 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -579,7 +579,7 @@ public class NumberPicker extends LinearLayout { throw new IllegalArgumentException("minWidth > maxWidth"); } - mComputeMaxWidth = (mMaxWidth == Integer.MAX_VALUE); + mComputeMaxWidth = (mMaxWidth == SIZE_UNSPECIFIED); attributesArray.recycle(); @@ -771,6 +771,8 @@ public class NumberPicker extends LinearLayout { mLastDownEventTime = event.getEventTime(); mIngonreMoveEvents = false; mShowSoftInputOnTap = false; + // Make sure we wupport flinging inside scrollables. + getParent().requestDisallowInterceptTouchEvent(true); if (!mFlingScroller.isFinished()) { mFlingScroller.forceFinished(true); mAdjustScroller.forceFinished(true); @@ -1096,12 +1098,7 @@ public class NumberPicker extends LinearLayout { * @see #setMaxValue(int) */ public void setValue(int value) { - if (mValue == value) { - return; - } setValueInternal(value, false); - initializeSelectorWheelIndices(); - invalidate(); } /** @@ -1498,6 +1495,8 @@ public class NumberPicker extends LinearLayout { if (notifyChange) { notifyChange(previous, current); } + initializeSelectorWheelIndices(); + invalidate(); } /** diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index 3bc4f7f..0b49404 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -37,9 +37,11 @@ import android.graphics.drawable.shapes.RoundRectShape; import android.graphics.drawable.shapes.Shape; import android.os.Parcel; import android.os.Parcelable; -import android.os.SystemClock; import android.util.AttributeSet; -import android.view.Choreographer; +import android.util.Pool; +import android.util.Poolable; +import android.util.PoolableManager; +import android.util.Pools; import android.view.Gravity; import android.view.RemotableViewMethod; import android.view.View; @@ -55,6 +57,8 @@ import android.view.animation.LinearInterpolator; import android.view.animation.Transformation; import android.widget.RemoteViews.RemoteView; +import java.util.ArrayList; + /** * <p> @@ -218,6 +222,10 @@ public class ProgressBar extends View { private boolean mShouldStartAnimationDrawable; private boolean mInDrawing; + private boolean mAttached; + private boolean mRefreshIsPosted; + + private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>(); private AccessibilityEventSender mAccessibilityEventSender; @@ -558,29 +566,76 @@ public class ProgressBar extends View { } private class RefreshProgressRunnable implements Runnable { + public void run() { + synchronized (ProgressBar.this) { + final int count = mRefreshData.size(); + for (int i = 0; i < count; i++) { + final RefreshData rd = mRefreshData.get(i); + doRefreshProgress(rd.id, rd.progress, rd.fromUser, true); + rd.recycle(); + } + mRefreshData.clear(); + mRefreshIsPosted = false; + } + } + } - private int mId; - private int mProgress; - private boolean mFromUser; + private static class RefreshData implements Poolable<RefreshData> { + public int id; + public int progress; + public boolean fromUser; - RefreshProgressRunnable(int id, int progress, boolean fromUser) { - mId = id; - mProgress = progress; - mFromUser = fromUser; - } + private RefreshData mNext; + private boolean mIsPooled; - public void run() { - doRefreshProgress(mId, mProgress, mFromUser, true); - // Put ourselves back in the cache when we are done - mRefreshProgressRunnable = this; + private static final int POOL_MAX = 24; + private static final Pool<RefreshData> sPool = Pools.synchronizedPool( + Pools.finitePool(new PoolableManager<RefreshData>() { + @Override + public RefreshData newInstance() { + return new RefreshData(); + } + + @Override + public void onAcquired(RefreshData element) { + } + + @Override + public void onReleased(RefreshData element) { + } + }, POOL_MAX)); + + public static RefreshData obtain(int id, int progress, boolean fromUser) { + RefreshData rd = sPool.acquire(); + rd.id = id; + rd.progress = progress; + rd.fromUser = fromUser; + return rd; } - public void setup(int id, int progress, boolean fromUser) { - mId = id; - mProgress = progress; - mFromUser = fromUser; + public void recycle() { + sPool.release(this); + } + + @Override + public void setNextPoolable(RefreshData element) { + mNext = element; + } + + @Override + public RefreshData getNextPoolable() { + return mNext; + } + + @Override + public boolean isPooled() { + return mIsPooled; + } + + @Override + public void setPooled(boolean isPooled) { + mIsPooled = isPooled; } - } private synchronized void doRefreshProgress(int id, int progress, boolean fromUser, @@ -619,14 +674,16 @@ public class ProgressBar extends View { if (mRefreshProgressRunnable != null) { // Use cached RefreshProgressRunnable if available r = mRefreshProgressRunnable; - // Uncache it - mRefreshProgressRunnable = null; - r.setup(id, progress, fromUser); } else { // Make a new one - r = new RefreshProgressRunnable(id, progress, fromUser); + r = new RefreshProgressRunnable(); + } + final RefreshData rd = RefreshData.obtain(id, progress, fromUser); + mRefreshData.add(rd); + if (mAttached && !mRefreshIsPosted) { + post(r); + mRefreshIsPosted = true; } - post(r); } } @@ -1092,6 +1149,18 @@ public class ProgressBar extends View { if (mIndeterminate) { startAnimation(); } + if (mRefreshData != null) { + synchronized (this) { + final int count = mRefreshData.size(); + for (int i = 0; i < count; i++) { + final RefreshData rd = mRefreshData.get(i); + doRefreshProgress(rd.id, rd.progress, rd.fromUser, true); + rd.recycle(); + } + mRefreshData.clear(); + } + } + mAttached = true; } @Override @@ -1099,7 +1168,10 @@ public class ProgressBar extends View { if (mIndeterminate) { stopAnimation(); } - if(mRefreshProgressRunnable != null) { + if (mRefreshProgressRunnable != null) { + removeCallbacks(mRefreshProgressRunnable); + } + if (mRefreshProgressRunnable != null && mRefreshIsPosted) { removeCallbacks(mRefreshProgressRunnable); } if (mAccessibilityEventSender != null) { @@ -1108,6 +1180,7 @@ public class ProgressBar extends View { // This should come after stopAnimation(), otherwise an invalidate message remains in the // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation super.onDetachedFromWindow(); + mAttached = false; } @Override diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index e0e3e93..0f0dbae 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -73,7 +73,7 @@ public class ScrollView extends FrameLayout { /** * Position of the last motion event. */ - private float mLastMotionY; + private int mLastMotionY; /** * True when the layout has changed but the traversal has not come through yet. @@ -472,8 +472,8 @@ public class ScrollView extends FrameLayout { } final int pointerIndex = ev.findPointerIndex(activePointerId); - final float y = ev.getY(pointerIndex); - final int yDiff = (int) Math.abs(y - mLastMotionY); + final int y = (int) ev.getY(pointerIndex); + final int yDiff = Math.abs(y - mLastMotionY); if (yDiff > mTouchSlop) { mIsBeingDragged = true; mLastMotionY = y; @@ -487,7 +487,7 @@ public class ScrollView extends FrameLayout { } case MotionEvent.ACTION_DOWN: { - final float y = ev.getY(); + final int y = (int) ev.getY(); if (!inChild((int) ev.getX(), (int) y)) { mIsBeingDragged = false; recycleVelocityTracker(); @@ -522,7 +522,7 @@ public class ScrollView extends FrameLayout { mActivePointerId = INVALID_POINTER; recycleVelocityTracker(); if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) { - invalidate(); + postInvalidateOnAnimation(); } break; case MotionEvent.ACTION_POINTER_UP: @@ -564,7 +564,7 @@ public class ScrollView extends FrameLayout { } // Remember where the motion event started - mLastMotionY = ev.getY(); + mLastMotionY = (int) ev.getY(); mActivePointerId = ev.getPointerId(0); break; } @@ -572,8 +572,8 @@ public class ScrollView extends FrameLayout { if (mIsBeingDragged) { // Scroll to follow the motion event final int activePointerIndex = ev.findPointerIndex(mActivePointerId); - final float y = ev.getY(activePointerIndex); - final int deltaY = (int) (mLastMotionY - y); + final int y = (int) ev.getY(activePointerIndex); + final int deltaY = mLastMotionY - y; mLastMotionY = y; final int oldX = mScrollX; @@ -605,7 +605,7 @@ public class ScrollView extends FrameLayout { } if (mEdgeGlowTop != null && (!mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished())) { - invalidate(); + postInvalidateOnAnimation(); } } } @@ -622,7 +622,7 @@ public class ScrollView extends FrameLayout { } else { if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) { - invalidate(); + postInvalidateOnAnimation(); } } } @@ -634,7 +634,7 @@ public class ScrollView extends FrameLayout { case MotionEvent.ACTION_CANCEL: if (mIsBeingDragged && getChildCount() > 0) { if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) { - invalidate(); + postInvalidateOnAnimation(); } mActivePointerId = INVALID_POINTER; endDrag(); @@ -642,13 +642,13 @@ public class ScrollView extends FrameLayout { break; case MotionEvent.ACTION_POINTER_DOWN: { final int index = ev.getActionIndex(); - mLastMotionY = ev.getY(index); + mLastMotionY = (int) ev.getY(index); mActivePointerId = ev.getPointerId(index); break; } case MotionEvent.ACTION_POINTER_UP: onSecondaryPointerUp(ev); - mLastMotionY = ev.getY(ev.findPointerIndex(mActivePointerId)); + mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId)); break; } return true; @@ -663,7 +663,7 @@ public class ScrollView extends FrameLayout { // active pointer and adjust accordingly. // TODO: Make this decision more intelligent. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; - mLastMotionY = ev.getY(newPointerIndex); + mLastMotionY = (int) ev.getY(newPointerIndex); mActivePointerId = ev.getPointerId(newPointerIndex); if (mVelocityTracker != null) { mVelocityTracker.clear(); @@ -1047,7 +1047,7 @@ public class ScrollView extends FrameLayout { dy = Math.max(0, Math.min(scrollY + dy, maxY)) - scrollY; mScroller.startScroll(mScrollX, scrollY, 0, dy); - invalidate(); + postInvalidateOnAnimation(); } else { if (!mScroller.isFinished()) { mScroller.abortAnimation(); @@ -1174,7 +1174,7 @@ public class ScrollView extends FrameLayout { if (!awakenScrollBars()) { // Keep on drawing until the animation has finished. - invalidate(); + postInvalidateOnAnimation(); } } else { if (mFlingStrictSpan != null) { @@ -1430,7 +1430,7 @@ public class ScrollView extends FrameLayout { mFlingStrictSpan = StrictMode.enterCriticalSpan("ScrollView-fling"); } - invalidate(); + postInvalidateOnAnimation(); } } @@ -1495,7 +1495,7 @@ public class ScrollView extends FrameLayout { canvas.translate(mPaddingLeft, Math.min(0, scrollY)); mEdgeGlowTop.setSize(width, getHeight()); if (mEdgeGlowTop.draw(canvas)) { - invalidate(); + postInvalidateOnAnimation(); } canvas.restoreToCount(restoreCount); } @@ -1509,7 +1509,7 @@ public class ScrollView extends FrameLayout { canvas.rotate(180, width, 0); mEdgeGlowBottom.setSize(width, height); if (mEdgeGlowBottom.draw(canvas)) { - invalidate(); + postInvalidateOnAnimation(); } canvas.restoreToCount(restoreCount); } diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index 9afaee3..c725b64 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -227,8 +227,7 @@ public class SpellChecker implements SpellCheckerSessionListener { for (int i = 0; i < length; i++) { final SpellParser spellParser = mSpellParsers[i]; if (spellParser.isFinished()) { - spellParser.init(start, end); - spellParser.parse(); + spellParser.parse(start, end); return; } } @@ -240,8 +239,7 @@ public class SpellChecker implements SpellCheckerSessionListener { SpellParser spellParser = new SpellParser(); mSpellParsers[length] = spellParser; - spellParser.init(start, end); - spellParser.parse(); + spellParser.parse(start, end); } private void spellCheck() { @@ -421,8 +419,11 @@ public class SpellChecker implements SpellCheckerSessionListener { private class SpellParser { private Object mRange = new Object(); - public void init(int start, int end) { - setRangeSpan((Editable) mTextView.getText(), start, end); + public void parse(int start, int end) { + if (end > start) { + setRangeSpan((Editable) mTextView.getText(), start, end); + parse(); + } } public boolean isFinished() { diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index aef8a34..36d1ee0 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -907,7 +907,7 @@ public class Spinner extends AbsSpinner implements OnClickListener { public void onItemClick(AdapterView parent, View v, int position, long id) { Spinner.this.setSelection(position); if (mOnItemClickListener != null) { - Spinner.this.performItemClick(null, position, mAdapter.getItemId(position)); + Spinner.this.performItemClick(v, position, mAdapter.getItemId(position)); } dismiss(); } diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java index a897cc3..0786909 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -806,5 +806,16 @@ public class Switch extends CompoundButton { public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(Switch.class.getName()); + CharSequence switchText = isChecked() ? mTextOn : mTextOff; + if (!TextUtils.isEmpty(switchText)) { + CharSequence oldText = info.getText(); + if (TextUtils.isEmpty(oldText)) { + info.setText(switchText); + } else { + StringBuilder newText = new StringBuilder(); + newText.append(oldText).append(' ').append(switchText); + info.setText(newText); + } + } } } diff --git a/core/java/com/android/internal/policy/IFaceLockInterface.aidl b/core/java/com/android/internal/policy/IFaceLockInterface.aidl index 3958cda..017801b 100644 --- a/core/java/com/android/internal/policy/IFaceLockInterface.aidl +++ b/core/java/com/android/internal/policy/IFaceLockInterface.aidl @@ -20,7 +20,8 @@ import com.android.internal.policy.IFaceLockCallback; /** {@hide} */ interface IFaceLockInterface { - void startUi(IBinder containingWindowToken, int x, int y, int width, int height); + void startUi(IBinder containingWindowToken, int x, int y, int width, int height, + boolean useLiveliness); void stopUi(); void registerCallback(IFaceLockCallback cb); void unregisterCallback(IFaceLockCallback cb); diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java index e00fe9f..af67d55 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuView.java @@ -340,8 +340,12 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec); final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode); + final ActionMenuItemView itemView = child instanceof ActionMenuItemView ? + (ActionMenuItemView) child : null; + final boolean hasText = itemView != null && itemView.hasText(); + int cellsUsed = 0; - if (cellsRemaining > 0) { + if (cellsRemaining > 0 && (!hasText || cellsRemaining >= 2)) { final int childWidthSpec = MeasureSpec.makeMeasureSpec( cellSize * cellsRemaining, MeasureSpec.AT_MOST); child.measure(childWidthSpec, childHeightSpec); @@ -349,11 +353,10 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo final int measuredWidth = child.getMeasuredWidth(); cellsUsed = measuredWidth / cellSize; if (measuredWidth % cellSize != 0) cellsUsed++; + if (hasText && cellsUsed < 2) cellsUsed = 2; } - final ActionMenuItemView itemView = child instanceof ActionMenuItemView ? - (ActionMenuItemView) child : null; - final boolean expandable = !lp.isOverflowButton && itemView != null && itemView.hasText(); + final boolean expandable = !lp.isOverflowButton && hasText; lp.expandable = expandable; lp.cellsUsed = cellsUsed; diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 4d308dd..f77e8f3 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -223,6 +223,14 @@ public class LockPatternUtils { } } + public int getCurrentUser() { + if (Process.myUid() == Process.SYSTEM_UID) { + return mCurrentUserId; + } else { + throw new SecurityException("Only the system process can get the current user"); + } + } + public void removeUser(int userId) { if (Process.myUid() == Process.SYSTEM_UID) { try { diff --git a/core/jni/Android.mk b/core/jni/Android.mk index ec0fe00..523b2d5 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -48,6 +48,7 @@ LOCAL_SRC_FILES:= \ android_view_Surface.cpp \ android_view_TextureView.cpp \ android_view_InputChannel.cpp \ + android_view_InputDevice.cpp \ android_view_InputEventReceiver.cpp \ android_view_KeyEvent.cpp \ android_view_KeyCharacterMap.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index e705c47..b877071 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -148,7 +148,6 @@ extern int register_android_net_TrafficStats(JNIEnv* env); extern int register_android_net_wifi_WifiManager(JNIEnv* env); extern int register_android_text_AndroidCharacter(JNIEnv *env); extern int register_android_text_AndroidBidi(JNIEnv *env); -extern int register_android_text_KeyCharacterMap(JNIEnv *env); extern int register_android_opengl_classes(JNIEnv *env); extern int register_android_bluetooth_HeadsetBase(JNIEnv* env); extern int register_android_bluetooth_BluetoothAudioGateway(JNIEnv* env); @@ -168,7 +167,9 @@ extern int register_android_app_backup_FullBackup(JNIEnv *env); extern int register_android_app_ActivityThread(JNIEnv *env); extern int register_android_app_NativeActivity(JNIEnv *env); extern int register_android_view_InputChannel(JNIEnv* env); +extern int register_android_view_InputDevice(JNIEnv* env); extern int register_android_view_InputEventReceiver(JNIEnv* env); +extern int register_android_view_KeyCharacterMap(JNIEnv *env); extern int register_android_view_KeyEvent(JNIEnv* env); extern int register_android_view_MotionEvent(JNIEnv* env); extern int register_android_view_PointerIcon(JNIEnv* env); @@ -548,6 +549,10 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) opt.optionString = heapsizeOptsBuf; mOptions.add(opt); + // Increase the main thread's interpreter stack size for bug 6315322. + opt.optionString = "-XX:mainThreadStackSize=24K"; + mOptions.add(opt); + strcpy(heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit="); property_get("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf+20, ""); if (heapgrowthlimitOptsBuf[20] != '\0') { @@ -1082,7 +1087,8 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_emoji_EmojiFactory), REG_JNI(register_android_text_AndroidCharacter), REG_JNI(register_android_text_AndroidBidi), - REG_JNI(register_android_text_KeyCharacterMap), + REG_JNI(register_android_view_InputDevice), + REG_JNI(register_android_view_KeyCharacterMap), REG_JNI(register_android_os_Process), REG_JNI(register_android_os_SystemProperties), REG_JNI(register_android_os_Binder), diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 376c841..a65262c 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -254,6 +254,13 @@ public: obj->setTextAlign(align); } + static void setTextLocale(JNIEnv* env, jobject clazz, SkPaint* obj, jstring locale) { + const char* localeArray = env->GetStringUTFChars(locale, NULL); + SkString skLocale(localeArray); + obj->setTextLocale(skLocale); + env->ReleaseStringUTFChars(locale, localeArray); + } + static jfloat getTextSize(JNIEnv* env, jobject paint) { NPE_CHECK_RETURN_ZERO(env, paint); return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSize()); @@ -817,6 +824,7 @@ static JNINativeMethod methods[] = { {"native_setRasterizer","(II)I", (void*) SkPaintGlue::setRasterizer}, {"native_getTextAlign","(I)I", (void*) SkPaintGlue::getTextAlign}, {"native_setTextAlign","(II)V", (void*) SkPaintGlue::setTextAlign}, + {"native_setTextLocale","(ILjava/lang/String;)V", (void*) SkPaintGlue::setTextLocale}, {"getTextSize","()F", (void*) SkPaintGlue::getTextSize}, {"setTextSize","(F)V", (void*) SkPaintGlue::setTextSize}, {"getTextScaleX","()F", (void*) SkPaintGlue::getTextScaleX}, diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index a7abbfa..a97c710 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -29,10 +29,7 @@ extern "C" { namespace android { //-------------------------------------------------------------------------------------------------- -// Using DroidSansArabic for shaping Arabic with Harfbuzz because its metrics are more compatible -// with the "Roboto" metrics (compared to DroidNaskh-Regular). When we will have an Arabic font -// whose metrics are similar to the Roboto ones, then we will need to use it for shaping. -#define TYPEFACE_ARABIC "/system/fonts/DroidSansArabic.ttf" +#define TYPEFACE_ARABIC "/system/fonts/DroidNaskh-Regular-Shift.ttf" #define TYPE_FACE_HEBREW_REGULAR "/system/fonts/DroidSansHebrew-Regular.ttf" #define TYPE_FACE_HEBREW_BOLD "/system/fonts/DroidSansHebrew-Bold.ttf" #define TYPEFACE_BENGALI "/system/fonts/Lohit-Bengali.ttf" diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp new file mode 100644 index 0000000..d7d476a --- /dev/null +++ b/core/jni/android_view_InputDevice.cpp @@ -0,0 +1,97 @@ +/* + * 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 <androidfw/Input.h> + +#include <android_runtime/AndroidRuntime.h> +#include <nativehelper/jni.h> +#include <nativehelper/JNIHelp.h> + +#include <ScopedLocalRef.h> + +#include "android_view_InputDevice.h" +#include "android_view_KeyCharacterMap.h" + +namespace android { + +static struct { + jclass clazz; + + jmethodID ctor; + jmethodID addMotionRange; +} gInputDeviceClassInfo; + +jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& deviceInfo) { + ScopedLocalRef<jstring> nameObj(env, env->NewStringUTF(deviceInfo.getName().string())); + if (!nameObj.get()) { + return NULL; + } + + ScopedLocalRef<jstring> descriptorObj(env, + env->NewStringUTF(deviceInfo.getDescriptor().string())); + if (!descriptorObj.get()) { + return NULL; + } + + ScopedLocalRef<jobject> kcmObj(env, + android_view_KeyCharacterMap_create(env, deviceInfo.getId(), + deviceInfo.getKeyCharacterMap())); + if (!kcmObj.get()) { + return NULL; + } + + ScopedLocalRef<jobject> inputDeviceObj(env, env->NewObject(gInputDeviceClassInfo.clazz, + gInputDeviceClassInfo.ctor, deviceInfo.getId(), nameObj.get(), + descriptorObj.get(), deviceInfo.getSources(), deviceInfo.getKeyboardType(), + kcmObj.get())); + + const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); + for (size_t i = 0; i < ranges.size(); i++) { + const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); + env->CallVoidMethod(inputDeviceObj.get(), gInputDeviceClassInfo.addMotionRange, + range.axis, range.source, range.min, range.max, range.flat, range.fuzz); + if (env->ExceptionCheck()) { + return NULL; + } + } + + return env->NewLocalRef(inputDeviceObj.get()); +} + + +#define FIND_CLASS(var, className) \ + var = env->FindClass(className); \ + LOG_FATAL_IF(! var, "Unable to find class " className); + +#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ + var = env->GetMethodID(clazz, methodName, methodDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find method " methodName); + +int register_android_view_InputDevice(JNIEnv* env) +{ + FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice"); + gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz)); + + GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz, + "<init>", "(ILjava/lang/String;Ljava/lang/String;IILandroid/view/KeyCharacterMap;)V"); + + GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz, + "addMotionRange", "(IIFFFF)V"); + + return 0; +} + +}; // namespace android diff --git a/core/jni/android_view_InputDevice.h b/core/jni/android_view_InputDevice.h new file mode 100644 index 0000000..78651ba --- /dev/null +++ b/core/jni/android_view_InputDevice.h @@ -0,0 +1,31 @@ +/* + * 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 _ANDROID_VIEW_INPUTDEVICE_H +#define _ANDROID_VIEW_INPUTDEVICE_H + +#include "jni.h" + +#include <androidfw/InputDevice.h> + +namespace android { + +/* Creates an InputDevice object from the given information. */ +extern jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& deviceInfo); + +} // namespace android + +#endif // _ANDROID_VIEW_INPUTDEVICE_H diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index 348437d..8f6f5f4 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -52,8 +52,7 @@ public: status_t initialize(); status_t finishInputEvent(uint32_t seq, bool handled); - status_t consumeEvents(bool consumeBatches); - static int handleReceiveCallback(int receiveFd, int events, void* data); + status_t consumeEvents(JNIEnv* env, bool consumeBatches); protected: virtual ~NativeInputEventReceiver(); @@ -68,6 +67,8 @@ private: const char* getInputChannelName() { return mInputConsumer.getChannel()->getName().string(); } + + static int handleReceiveCallback(int receiveFd, int events, void* data); }; @@ -128,11 +129,13 @@ int NativeInputEventReceiver::handleReceiveCallback(int receiveFd, int events, v return 1; } - status_t status = r->consumeEvents(false /*consumeBatches*/); + JNIEnv* env = AndroidRuntime::getJNIEnv(); + status_t status = r->consumeEvents(env, false /*consumeBatches*/); + r->mMessageQueue->raiseAndClearException(env, "handleReceiveCallback"); return status == OK || status == NO_MEMORY ? 1 : 0; } -status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) { +status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, bool consumeBatches) { #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s.", getInputChannelName(), consumeBatches ? "true" : "false"); @@ -142,7 +145,7 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) { mBatchedInputEventPending = false; } - JNIEnv* env = AndroidRuntime::getJNIEnv(); + bool skipCallbacks = false; for (;;) { uint32_t seq; InputEvent* inputEvent; @@ -150,7 +153,8 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) { consumeBatches, &seq, &inputEvent); if (status) { if (status == WOULD_BLOCK) { - if (mInputConsumer.hasPendingBatch() && !mBatchedInputEventPending) { + if (!skipCallbacks && !mBatchedInputEventPending + && mInputConsumer.hasPendingBatch()) { // There is a pending batch. Come back later. mBatchedInputEventPending = true; #if DEBUG_DISPATCH_CYCLE @@ -159,8 +163,8 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) { #endif env->CallVoidMethod(mReceiverObjGlobal, gInputEventReceiverClassInfo.dispatchBatchedInputEventPending); - if (mMessageQueue->raiseAndClearException( - env, "dispatchBatchedInputEventPending")) { + if (env->ExceptionCheck()) { + ALOGE("Exception dispatching batched input events."); mBatchedInputEventPending = false; // try again later } } @@ -172,46 +176,47 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) { } assert(inputEvent); - jobject inputEventObj; - switch (inputEvent->getType()) { - case AINPUT_EVENT_TYPE_KEY: + if (!skipCallbacks) { + jobject inputEventObj; + switch (inputEvent->getType()) { + case AINPUT_EVENT_TYPE_KEY: #if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ Received key event.", getInputChannelName()); + ALOGD("channel '%s' ~ Received key event.", getInputChannelName()); #endif - inputEventObj = android_view_KeyEvent_fromNative(env, - static_cast<KeyEvent*>(inputEvent)); - mMessageQueue->raiseAndClearException(env, "new KeyEvent"); - break; + inputEventObj = android_view_KeyEvent_fromNative(env, + static_cast<KeyEvent*>(inputEvent)); + break; - case AINPUT_EVENT_TYPE_MOTION: + case AINPUT_EVENT_TYPE_MOTION: #if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ Received motion event.", getInputChannelName()); + ALOGD("channel '%s' ~ Received motion event.", getInputChannelName()); #endif - inputEventObj = android_view_MotionEvent_obtainAsCopy(env, - static_cast<MotionEvent*>(inputEvent)); - mMessageQueue->raiseAndClearException(env, "new MotionEvent"); - break; - - default: - assert(false); // InputConsumer should prevent this from ever happening - inputEventObj = NULL; - } + inputEventObj = android_view_MotionEvent_obtainAsCopy(env, + static_cast<MotionEvent*>(inputEvent)); + break; - if (!inputEventObj) { - ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName()); - mInputConsumer.sendFinishedSignal(seq, false); - continue; - } + default: + assert(false); // InputConsumer should prevent this from ever happening + inputEventObj = NULL; + } + if (inputEventObj) { #if DEBUG_DISPATCH_CYCLE - ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName()); + ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName()); #endif - env->CallVoidMethod(mReceiverObjGlobal, - gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj); - - env->DeleteLocalRef(inputEventObj); + env->CallVoidMethod(mReceiverObjGlobal, + gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj); + if (env->ExceptionCheck()) { + ALOGE("Exception dispatching input event."); + skipCallbacks = true; + } + } else { + ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName()); + skipCallbacks = true; + } + } - if (mMessageQueue->raiseAndClearException(env, "dispatchInputEvent")) { + if (skipCallbacks) { mInputConsumer.sendFinishedSignal(seq, false); } } @@ -268,8 +273,8 @@ static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr, static void nativeConsumeBatchedInputEvents(JNIEnv* env, jclass clazz, jint receiverPtr) { sp<NativeInputEventReceiver> receiver = reinterpret_cast<NativeInputEventReceiver*>(receiverPtr); - status_t status = receiver->consumeEvents(true /*consumeBatches*/); - if (status && status != DEAD_OBJECT) { + status_t status = receiver->consumeEvents(env, true /*consumeBatches*/); + if (status && status != DEAD_OBJECT && !env->ExceptionCheck()) { String8 message; message.appendFormat("Failed to consume batched input event. status=%d", status); jniThrowRuntimeException(env, message.string()); diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp index 7245d9d..3e56a89 100644 --- a/core/jni/android_view_KeyCharacterMap.cpp +++ b/core/jni/android_view_KeyCharacterMap.cpp @@ -14,19 +14,27 @@ * limitations under the License. */ +#include <android_runtime/AndroidRuntime.h> + #include <androidfw/KeyCharacterMap.h> #include <androidfw/Input.h> +#include <binder/Parcel.h> -#include <android_runtime/AndroidRuntime.h> #include <nativehelper/jni.h> #include <nativehelper/JNIHelp.h> +#include "android_os_Parcel.h" #include "android_view_KeyEvent.h" namespace android { static struct { jclass clazz; + jmethodID ctor; +} gKeyCharacterMapClassInfo; + +static struct { + jclass clazz; } gKeyEventClassInfo; static struct { @@ -35,44 +43,87 @@ static struct { } gFallbackActionClassInfo; -static jint nativeLoad(JNIEnv *env, jobject clazz, jstring fileStr) { - const char* file = env->GetStringUTFChars(fileStr, NULL); - - KeyCharacterMap* map; - status_t status = KeyCharacterMap::load(String8(file), &map); - jint result; - if (status) { - String8 msg; - msg.appendFormat("Could not load key character map '%s' due to error %d. " - "Refer to the log for details.", file, status); - jniThrowException(env, "android/view/KeyCharacterMap$KeyCharacterMapUnavailableException", - msg.string()); - result = 0; - } else { - result = reinterpret_cast<jint>(map); +class NativeKeyCharacterMap { +public: + NativeKeyCharacterMap(int32_t deviceId, const sp<KeyCharacterMap>& map) : + mDeviceId(deviceId), mMap(map) { } - env->ReleaseStringUTFChars(fileStr, file); - return result; + ~NativeKeyCharacterMap() { + } + + inline int32_t getDeviceId() const { + return mDeviceId; + } + + inline const sp<KeyCharacterMap>& getMap() const { + return mMap; + } + +private: + int32_t mDeviceId; + sp<KeyCharacterMap> mMap; +}; + + +jobject android_view_KeyCharacterMap_create(JNIEnv* env, int32_t deviceId, + const sp<KeyCharacterMap>& kcm) { + NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId, + kcm.get() ? kcm : KeyCharacterMap::empty()); + if (!map) { + return NULL; + } + + return env->NewObject(gKeyCharacterMapClassInfo.clazz, gKeyCharacterMapClassInfo.ctor, + reinterpret_cast<jint>(map)); +} + +static jint nativeReadFromParcel(JNIEnv *env, jobject clazz, jobject parcelObj) { + Parcel* parcel = parcelForJavaObject(env, parcelObj); + if (!parcel) { + return 0; + } + + int32_t deviceId = parcel->readInt32(); + if (parcel->errorCheck()) { + return 0; + } + + sp<KeyCharacterMap> kcm = KeyCharacterMap::readFromParcel(parcel); + if (!kcm.get()) { + return 0; + } + + NativeKeyCharacterMap* map = new NativeKeyCharacterMap(deviceId, kcm); + return reinterpret_cast<jint>(map); +} + +static void nativeWriteToParcel(JNIEnv* env, jobject clazz, jint ptr, jobject parcelObj) { + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); + Parcel* parcel = parcelForJavaObject(env, parcelObj); + if (parcel) { + parcel->writeInt32(map->getDeviceId()); + map->getMap()->writeToParcel(parcel); + } } static void nativeDispose(JNIEnv *env, jobject clazz, jint ptr) { - KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); delete map; } static jchar nativeGetCharacter(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, jint metaState) { - KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); - return map->getCharacter(keyCode, metaState); + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); + return map->getMap()->getCharacter(keyCode, metaState); } static jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, jint metaState, jobject fallbackActionObj) { - KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); KeyCharacterMap::FallbackAction fallbackAction; - bool result = map->getFallbackAction(keyCode, metaState, &fallbackAction); + bool result = map->getMap()->getFallbackAction(keyCode, metaState, &fallbackAction); if (result) { env->SetIntField(fallbackActionObj, gFallbackActionClassInfo.keyCode, fallbackAction.keyCode); @@ -83,13 +134,13 @@ static jboolean nativeGetFallbackAction(JNIEnv *env, jobject clazz, jint ptr, ji } static jchar nativeGetNumber(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) { - KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); - return map->getNumber(keyCode); + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); + return map->getMap()->getNumber(keyCode); } static jchar nativeGetMatch(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, jcharArray charsArray, jint metaState) { - KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); jsize numChars = env->GetArrayLength(charsArray); jchar* chars = static_cast<jchar*>(env->GetPrimitiveArrayCritical(charsArray, NULL)); @@ -97,25 +148,25 @@ static jchar nativeGetMatch(JNIEnv *env, jobject clazz, jint ptr, jint keyCode, return 0; } - char16_t result = map->getMatch(keyCode, chars, size_t(numChars), metaState); + char16_t result = map->getMap()->getMatch(keyCode, chars, size_t(numChars), metaState); env->ReleasePrimitiveArrayCritical(charsArray, chars, JNI_ABORT); return result; } static jchar nativeGetDisplayLabel(JNIEnv *env, jobject clazz, jint ptr, jint keyCode) { - KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); - return map->getDisplayLabel(keyCode); + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); + return map->getMap()->getDisplayLabel(keyCode); } static jint nativeGetKeyboardType(JNIEnv *env, jobject clazz, jint ptr) { - KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); - return map->getKeyboardType(); + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); + return map->getMap()->getKeyboardType(); } -static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jint ptr, jint deviceId, +static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jint ptr, jcharArray charsArray) { - KeyCharacterMap* map = reinterpret_cast<KeyCharacterMap*>(ptr); + NativeKeyCharacterMap* map = reinterpret_cast<NativeKeyCharacterMap*>(ptr); jchar* chars = env->GetCharArrayElements(charsArray, NULL); if (!chars) { @@ -125,7 +176,7 @@ static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jint ptr, jint d Vector<KeyEvent> events; jobjectArray result = NULL; - if (map->getEvents(deviceId, chars, size_t(numChars), events)) { + if (map->getMap()->getEvents(map->getDeviceId(), chars, size_t(numChars), events)) { result = env->NewObjectArray(jsize(events.size()), gKeyEventClassInfo.clazz, NULL); if (result) { for (size_t i = 0; i < events.size(); i++) { @@ -148,8 +199,10 @@ static jobjectArray nativeGetEvents(JNIEnv *env, jobject clazz, jint ptr, jint d static JNINativeMethod g_methods[] = { /* name, signature, funcPtr */ - { "nativeLoad", "(Ljava/lang/String;)I", - (void*)nativeLoad }, + { "nativeReadFromParcel", "(Landroid/os/Parcel;)I", + (void*)nativeReadFromParcel }, + { "nativeWriteToParcel", "(ILandroid/os/Parcel;)V", + (void*)nativeWriteToParcel }, { "nativeDispose", "(I)V", (void*)nativeDispose }, { "nativeGetCharacter", "(III)C", @@ -164,7 +217,7 @@ static JNINativeMethod g_methods[] = { (void*)nativeGetDisplayLabel }, { "nativeGetKeyboardType", "(I)I", (void*)nativeGetKeyboardType }, - { "nativeGetEvents", "(II[C)[Landroid/view/KeyEvent;", + { "nativeGetEvents", "(I[C)[Landroid/view/KeyEvent;", (void*)nativeGetEvents }, }; @@ -172,12 +225,22 @@ static JNINativeMethod g_methods[] = { var = env->FindClass(className); \ LOG_FATAL_IF(! var, "Unable to find class " className); +#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ + var = env->GetMethodID(clazz, methodName, methodDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find method " methodName); + #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ LOG_FATAL_IF(! var, "Unable to find field " fieldName); -int register_android_text_KeyCharacterMap(JNIEnv* env) +int register_android_view_KeyCharacterMap(JNIEnv* env) { + FIND_CLASS(gKeyCharacterMapClassInfo.clazz, "android/view/KeyCharacterMap"); + gKeyCharacterMapClassInfo.clazz = jclass(env->NewGlobalRef(gKeyCharacterMapClassInfo.clazz)); + + GET_METHOD_ID(gKeyCharacterMapClassInfo.ctor, gKeyCharacterMapClassInfo.clazz, + "<init>", "(I)V"); + FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent"); gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz)); diff --git a/core/jni/android_view_KeyCharacterMap.h b/core/jni/android_view_KeyCharacterMap.h new file mode 100644 index 0000000..04024f6 --- /dev/null +++ b/core/jni/android_view_KeyCharacterMap.h @@ -0,0 +1,32 @@ +/* + * 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 _ANDROID_VIEW_KEY_CHARACTER_MAP_H +#define _ANDROID_VIEW_KEY_CHARACTER_MAP_H + +#include "jni.h" + +#include <androidfw/KeyCharacterMap.h> + +namespace android { + +/* Creates a KeyCharacterMap object from the given information. */ +extern jobject android_view_KeyCharacterMap_create(JNIEnv* env, int32_t deviceId, + const sp<KeyCharacterMap>& map); + +} // namespace android + +#endif // _ANDROID_VIEW_KEY_CHARACTER_MAP_H diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp index 5483867..9c6c7de 100644 --- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp @@ -178,7 +178,7 @@ static jboolean jni_eglQuerySurface(JNIEnv *_env, jobject _this, jobject display static jint jni_getInitCount(JNIEnv *_env, jobject _clazz, jobject display) { EGLDisplay dpy = getDisplay(_env, display); - egl_display_t* eglDisplay = get_display(dpy); + egl_display_t* eglDisplay = get_display_nowake(dpy); return eglDisplay ? eglDisplay->getRefsCount() : 0; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 00faa41..f5c0f8f 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1082,7 +1082,7 @@ <!-- Configure an application for debugging. --> <permission android:name="android.permission.SET_DEBUG_APP" android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS" - android:protectionLevel="dangerous" + android:protectionLevel="signature|system|development" android:label="@string/permlab_setDebugApp" android:description="@string/permdesc_setDebugApp" /> @@ -1090,7 +1090,7 @@ application processes that can be running. --> <permission android:name="android.permission.SET_PROCESS_LIMIT" android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS" - android:protectionLevel="dangerous" + android:protectionLevel="signature|system|development" android:label="@string/permlab_setProcessLimit" android:description="@string/permdesc_setProcessLimit" /> @@ -1098,14 +1098,14 @@ finished when put in the background. --> <permission android:name="android.permission.SET_ALWAYS_FINISH" android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS" - android:protectionLevel="dangerous" + android:protectionLevel="signature|system|development" android:label="@string/permlab_setAlwaysFinish" android:description="@string/permdesc_setAlwaysFinish" /> <!-- Allow an application to request that a signal be sent to all persistent processes --> <permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES" android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS" - android:protectionLevel="dangerous" + android:protectionLevel="signature|system|development" android:label="@string/permlab_signalPersistentProcesses" android:description="@string/permdesc_signalPersistentProcesses" /> @@ -1256,6 +1256,13 @@ android:description="@string/permdesc_setPointerSpeed" android:protectionLevel="signature" /> + <!-- Allows low-level access to setting the keyboard layout. + Not for use by normal applications. --> + <permission android:name="android.permission.SET_KEYBOARD_LAYOUT" + android:label="@string/permlab_setKeyboardLayout" + android:description="@string/permdesc_setKeyboardLayout" + android:protectionLevel="signature" /> + <!-- Allows an application to install packages. --> <permission android:name="android.permission.INSTALL_PACKAGES" android:label="@string/permlab_installPackages" diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml index 4f58be4..6b06456 100644 --- a/core/res/res/anim/lock_screen_behind_enter.xml +++ b/core/res/res/anim/lock_screen_behind_enter.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- /* -** Copyright 2007, The Android Open Source Project +** Copyright 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. @@ -18,7 +18,7 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:detachWallpaper="true" android:shareInterpolator="false"> + android:background="#ff000000" android:shareInterpolator="false"> <scale android:fromXScale="0.95" android:toXScale="1.0" android:fromYScale="0.95" android:toYScale="1.0" diff --git a/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml b/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml new file mode 100644 index 0000000..a354fae --- /dev/null +++ b/core/res/res/anim/lock_screen_wallpaper_behind_enter.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2007, 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. +*/ +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:detachWallpaper="true" android:shareInterpolator="false"> + <scale + android:fromXScale="0.95" android:toXScale="1.0" + android:fromYScale="0.95" android:toYScale="1.0" + android:pivotX="50%p" android:pivotY="50%p" + android:fillEnabled="true" android:fillBefore="true" + android:interpolator="@interpolator/decelerate_cubic" + android:startOffset="@android:integer/config_shortAnimTime" + android:duration="@android:integer/config_shortAnimTime" /> + <alpha + android:fromAlpha="0.0" android:toAlpha="1.0" + android:fillEnabled="true" android:fillBefore="true" + android:interpolator="@interpolator/decelerate_quad" + android:startOffset="@android:integer/config_shortAnimTime" + android:duration="@android:integer/config_shortAnimTime"/> +</set> diff --git a/core/res/res/anim/screen_rotate_180_enter.xml b/core/res/res/anim/screen_rotate_180_enter.xml index e2f3ce2..688a8d5 100644 --- a/core/res/res/anim/screen_rotate_180_enter.xml +++ b/core/res/res/anim/screen_rotate_180_enter.xml @@ -24,5 +24,5 @@ android:interpolator="@interpolator/decelerate_quint" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:duration="@android:integer/config_longAnimTime" /> + android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_180_exit.xml b/core/res/res/anim/screen_rotate_180_exit.xml index fe4a950..1eb6361 100644 --- a/core/res/res/anim/screen_rotate_180_exit.xml +++ b/core/res/res/anim/screen_rotate_180_exit.xml @@ -24,5 +24,8 @@ android:interpolator="@interpolator/decelerate_quint" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:duration="@android:integer/config_longAnimTime" /> + android:duration="@android:integer/config_mediumAnimTime" /> + <alpha android:fromAlpha="1.0" android:toAlpha="0" + android:interpolator="@interpolator/decelerate_cubic" + android:duration="@android:integer/config_mediumAnimTime"/> </set>
\ No newline at end of file diff --git a/core/res/res/anim/screen_rotate_180_frame.xml b/core/res/res/anim/screen_rotate_180_frame.xml index 1a3ee67..19dade1 100644 --- a/core/res/res/anim/screen_rotate_180_frame.xml +++ b/core/res/res/anim/screen_rotate_180_frame.xml @@ -24,5 +24,5 @@ android:interpolator="@interpolator/decelerate_quint" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" - android:duration="@android:integer/config_longAnimTime" /> + android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_minus_90_enter.xml b/core/res/res/anim/screen_rotate_minus_90_enter.xml index 38a674d..b16d5fc 100644 --- a/core/res/res/anim/screen_rotate_minus_90_enter.xml +++ b/core/res/res/anim/screen_rotate_minus_90_enter.xml @@ -19,10 +19,18 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> + <!-- Version for two-phase anim <rotate android:fromDegrees="-90" android:toDegrees="0" android:pivotX="50%" android:pivotY="50%" android:interpolator="@interpolator/decelerate_quint" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_longAnimTime" /> + --> + <rotate android:fromDegrees="-90" android:toDegrees="0" + android:pivotX="50%" android:pivotY="50%" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:interpolator="@interpolator/decelerate_quint" + android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_minus_90_exit.xml b/core/res/res/anim/screen_rotate_minus_90_exit.xml index a75aca7..9b38939 100644 --- a/core/res/res/anim/screen_rotate_minus_90_exit.xml +++ b/core/res/res/anim/screen_rotate_minus_90_exit.xml @@ -19,10 +19,30 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> + <!-- Version for two-phase animation <rotate android:fromDegrees="0" android:toDegrees="90" android:pivotX="50%" android:pivotY="50%" android:interpolator="@interpolator/decelerate_quint" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_longAnimTime" /> + --> + <scale android:fromXScale="100%" android:toXScale="100%p" + android:fromYScale="100%" android:toYScale="100%p" + android:pivotX="50%" android:pivotY="50%" + android:interpolator="@interpolator/decelerate_quint" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:duration="@android:integer/config_mediumAnimTime" /> + <rotate android:fromDegrees="0" android:toDegrees="90" + android:pivotX="50%" android:pivotY="50%" + android:interpolator="@interpolator/decelerate_quint" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:duration="@android:integer/config_mediumAnimTime" /> + <alpha android:fromAlpha="1.0" android:toAlpha="0" + android:interpolator="@interpolator/decelerate_quint" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_plus_90_enter.xml b/core/res/res/anim/screen_rotate_plus_90_enter.xml index 583d2ba..86a8d24 100644 --- a/core/res/res/anim/screen_rotate_plus_90_enter.xml +++ b/core/res/res/anim/screen_rotate_plus_90_enter.xml @@ -19,10 +19,18 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> + <!-- Version for two-phase animation <rotate android:fromDegrees="90" android:toDegrees="0" android:pivotX="50%" android:pivotY="50%" android:interpolator="@interpolator/decelerate_quint" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_longAnimTime" /> + --> + <rotate android:fromDegrees="90" android:toDegrees="0" + android:pivotX="50%" android:pivotY="50%" + android:interpolator="@interpolator/decelerate_quint" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/screen_rotate_plus_90_exit.xml b/core/res/res/anim/screen_rotate_plus_90_exit.xml index a2bef41..fa34533 100644 --- a/core/res/res/anim/screen_rotate_plus_90_exit.xml +++ b/core/res/res/anim/screen_rotate_plus_90_exit.xml @@ -19,10 +19,30 @@ <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> + <!-- Version for two-phase animation <rotate android:fromDegrees="0" android:toDegrees="-90" android:pivotX="50%" android:pivotY="50%" android:interpolator="@interpolator/decelerate_quint" android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true" android:duration="@android:integer/config_longAnimTime" /> + --> + <scale android:fromXScale="100%" android:toXScale="100%p" + android:fromYScale="100%" android:toYScale="100%p" + android:pivotX="50%" android:pivotY="50%" + android:interpolator="@interpolator/decelerate_quint" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:duration="@android:integer/config_mediumAnimTime" /> + <rotate android:fromDegrees="0" android:toDegrees="-90" + android:pivotX="50%" android:pivotY="50%" + android:interpolator="@interpolator/decelerate_quint" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:duration="@android:integer/config_mediumAnimTime" /> + <alpha android:fromAlpha="1.0" android:toAlpha="0" + android:interpolator="@interpolator/decelerate_quint" + android:fillEnabled="true" + android:fillBefore="true" android:fillAfter="true" + android:duration="@android:integer/config_mediumAnimTime" /> </set> diff --git a/core/res/res/anim/slow_fade_in.xml b/core/res/res/anim/slow_fade_in.xml new file mode 100644 index 0000000..21a2c78 --- /dev/null +++ b/core/res/res/anim/slow_fade_in.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/anim/fade_in.xml +** +** Copyright 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. +*/ +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@interpolator/decelerate_quad" + android:fromAlpha="0.0" android:toAlpha="1.0" + android:duration="1000" /> diff --git a/core/res/res/layout/input_method_switch_dialog_title.xml b/core/res/res/layout/input_method_switch_dialog_title.xml new file mode 100644 index 0000000..7032bd3 --- /dev/null +++ b/core/res/res/layout/input_method_switch_dialog_title.xml @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 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. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="9dip" + android:layout_marginLeft="20dip" + android:layout_marginRight="10dip" + android:layout_marginTop="6dip" + android:gravity="center_vertical" + android:orientation="vertical" > + + <com.android.internal.widget.DialogTitle + android:id="@+id/alertTitle" + style="@android:style/DialogWindowTitle.Holo" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:singleLine="true" + android:text="@string/select_input_method" /> + </LinearLayout> + + <!-- Hard keyboard switch --> + + <LinearLayout + android:id="@+id/hard_keyboard_section" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <View + android:layout_width="match_parent" + android:layout_height="2dip" + android:background="@android:color/holo_blue_light" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" > + + <LinearLayout + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:background="?android:attr/selectableItemBackground" + android:ellipsize="marquee" + android:gravity="center_vertical" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:orientation="vertical" + android:paddingBottom="5dip" + android:paddingLeft="16dip" + android:paddingRight="0dip" + android:paddingTop="5dip" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:text="@string/hardware" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:attr/textColorAlertDialogListItem" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:text="@string/use_physical_keyboard" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:attr/textColorAlertDialogListItem" /> + </LinearLayout> + + <Switch + android:id="@+id/hard_keyboard_switch" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginRight="12dip" /> + </LinearLayout> + </LinearLayout> + + <View + android:id="@+id/titleDivider" + android:layout_width="match_parent" + android:layout_height="2dip" + android:background="@android:drawable/divider_horizontal_dark" /> + +</LinearLayout>
\ No newline at end of file diff --git a/core/res/res/layout/notification_action.xml b/core/res/res/layout/notification_action.xml index 54fde70..785da7c 100644 --- a/core/res/res/layout/notification_action.xml +++ b/core/res/res/layout/notification_action.xml @@ -19,5 +19,5 @@ android:layout_width="match_parent" android:layout_height="wrap_content" style="@android:style/Widget.Holo.Button.Small" - android:gravity="left" + android:gravity="left|center_vertical" />
\ No newline at end of file diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index e649904..9528a7a 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Laat die program toe om die skerm se rotasie te eniger tyd te verander. Dit moet nooit vir normale programme nodig wees nie."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"verander wyserspoed"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Laat die program toe om die muis of stuurpaneel se wyserspoed te eniger tyd te verander. Dit moet nooit vir normale programme nodig wees nie."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"stuur Linux-seine na programme"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Laat die program toe om te versoek dat die voorsiende sein na alle aanhoudende prosesse gestuur word."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"laat program altyd loop"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Stel tyd"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Stel datum"</string> <string name="date_time_set" msgid="5777075614321087758">"Stel"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Klaar"</string> <string name="default_permission_group" msgid="2690160991405646128">"Verstek"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NUUT: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Geen toestemmings benodig nie"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Raak om USB-ontfouting te deaktiveer."</string> <string name="select_input_method" msgid="4653387336791222978">"Kies invoermetode"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Stel invoermetodes op"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidate"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Voeg \'n rekening by"</string> <string name="choose_account_text" msgid="6303348737197849675">"Watter rekening wil jy gebruik?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Voeg rekening by"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Vermeerder"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Verminder"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> raak en hou."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Gly op om te vermeeder en af om te verminder."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Vermeerder minuut"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Verminder minute"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Vermeerder uur"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Verminder uur"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Stel NM."</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Stel VM."</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Vermeerder maand"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Verminder maand"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Vermeerder dag"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Verminder dag"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Vermeerder jaar"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Verminder jaar"</string> <string name="checkbox_checked" msgid="7222044992652711167">"gekontroleer"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nie gekontroleer nie"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"gekies"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Deel met"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Deel met <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Skyfievatsel. Raak en hou."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Gly op vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Gly af vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Gly links vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Gly regs vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Ontsluit"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Stil"</string> <string name="description_target_soundon" msgid="30052466675500172">"Klank aan"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Soek"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Sleep om te ontsluit."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Prop \'n kopfoon in om te hoor hoe wagwoordsleutels hardop gesê word."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punt."</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 0203d82..747b12d 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"በማንኛውም ጊዜ የማሳያውን መሽከርከር ለመለወጥ ለመተግበሪያው ይፈቅዳሉ፡፡ ለተለመዱ መተግበሪያዎች አያስፈልግም፡፡"</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"የጠቋሚ ፍጥነት ለውጥ"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"መዳፊት ወይም ዱካ መከተያ ጠቋሚ ፍጥነትን በማንኛውም ጊዜ ለመለወጥ ለመተግበሪያው ይፈቅዳሉ፡፡ ለመደበኛ መተግበሪያዎች መቼም ቢሆን አያስፈልግም፡፡"</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"ወደ መተግበሪያዎችን የLinux ምልክቶች ላክ"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"ለሁሉም ተከታታይ ሂደቶች ልከው የሚያቀርቧቸው ሲግናሎችን ለመጠየቅ ለመተግበሪያው ይፈቅዳሉ።"</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"ትግበራ ሁልጊዜ አሂድ ላይ አድርግ"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"ጊዜ አዘጋጅ"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string> <string name="date_time_set" msgid="5777075614321087758">"አዘጋጅ"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"ተጠናቋል"</string> <string name="default_permission_group" msgid="2690160991405646128">"ነባሪ"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"አዲስ፦ "</font></string> <string name="no_permissions" msgid="7283357728219338112">"ምንም ፍቃዶች አይጠየቁም"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB ማረሚያ ላለማንቃት ዳስስ።"</string> <string name="select_input_method" msgid="4653387336791222978">"የግቤት ስልት ምረጥ"</string> <string name="configure_input_methods" msgid="9091652157722495116">"የግቤት ስልቶችን አዘጋጅ"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"ዕጩዎች"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"መለያ አክል"</string> <string name="choose_account_text" msgid="6303348737197849675">"የትኛውን መለያ መጠቀም ትፈልጋለህ?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"መለያ አክል"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"ጨምር"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"ቀንስ"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> ንካ እና ያዝ።"</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"ለመጨመር ወደ ላይ እና ለመቀነስ ወደ ታች አንሸራትት።"</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"ደቂቃ ጨምር"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"ደቂቃ ቀንስ"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"ሰዓት ጨምር"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"ሰዓት ቀንስ"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM አዘጋጅ"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM አዘጋጅ"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"ወር ጨምር"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"ወር ቀንስ"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"ቀን ጨምር"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ቀን ቀንስ"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"ዓመት ጨምር"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ዓመት ቀንስ"</string> <string name="checkbox_checked" msgid="7222044992652711167">"ታይቷል"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"አልተፈተሸም"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"የተመረጠ"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"ተጋራ ከ"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ከ <xliff:g id="APPLICATION_NAME">%s</xliff:g> ጋር ተጋራ"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"ባለስላይድ መያዣ፡፡ ዳስ&ያዝ፡፡"</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ላይ አንሸራትት።"</string> + <string name="description_direction_down" msgid="5087739728639014595">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ታች አንሸራትት።"</string> + <string name="description_direction_left" msgid="7207478719805562165">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ግራ አንሸራትት።"</string> + <string name="description_direction_right" msgid="8034433242579600980">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ቀኝ አንሸራትት።"</string> <string name="description_target_unlock" msgid="2228524900439801453">"ክፈት"</string> <string name="description_target_camera" msgid="969071997552486814">"ካሜራ"</string> <string name="description_target_silent" msgid="893551287746522182">"ፀጥታ"</string> <string name="description_target_soundon" msgid="30052466675500172">"ድምፅ አብራ"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"ፈልግ"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ላለመቆለፍ አንሸራት፡፡"</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"የይለፍ ቃል ቁልፎች ሲነገሩ ለመስማት የጆሮ ማዳመጫ ሰካ።"</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ነጥብ."</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index f0800c0..e95ea69 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"للسماح للتطبيق بتغيير تدوير الشاشة في أي وقت. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغيير سرعة المؤشر"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"للسماح للتطبيق بتغيير سرعة مؤشر الماوس أو لوحة التتبع في أي وقت. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"إرسال إشارات Linux للتطبيقات"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"للسماح للتطبيق بطلب إرسال الإشارة المزوّدة لجميع العمليات المستمرة."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"تشغيل التطبيق دائمًا"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"تعيين الوقت"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"تعيين التاريخ"</string> <string name="date_time_set" msgid="5777075614321087758">"تعيين"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"تم"</string> <string name="default_permission_group" msgid="2690160991405646128">"افتراضي"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"جديد: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"لا أذونات مطلوبة"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"المس لتعطيل تصحيح أخطاء USB."</string> <string name="select_input_method" msgid="4653387336791222978">"اختيار أسلوب الإدخال"</string> <string name="configure_input_methods" msgid="9091652157722495116">"إعداد أسلوب الإدخال"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"العناصر المرشحة"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"إضافة حساب"</string> <string name="choose_account_text" msgid="6303348737197849675">"ما الحساب الذي تريد استخدامه؟"</string> <string name="add_account_button_label" msgid="3611982894853435874">"إضافة حساب"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"زيادة"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"تقليل"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> المس مع الاستمرار."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"مرر لأعلى للزيادة ولأسفل للتقليل."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"زيادة الدقائق"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"تقليل الدقائق"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"زيادة الساعات"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"تقليل الساعات"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"تعيين المساء"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"تعيين الصباح"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"زيادة الشهور"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"تقليل الشهور"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"زيادة الأيام"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"تقليل الأيام"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"زيادة الأعوام"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"تقليل الأعوام"</string> <string name="checkbox_checked" msgid="7222044992652711167">"تم التحديد"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"لم يتم التحديد"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"محدد"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"مشاركة مع"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"مشاركة مع <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"مقبض التمرير. المس مع الاستمرار."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"تمرير لأعلى لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"تمرير لأسفل لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"تمرير لليسار لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"تمرير لليمين لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"إلغاء تأمين"</string> <string name="description_target_camera" msgid="969071997552486814">"الكاميرا"</string> <string name="description_target_silent" msgid="893551287746522182">"صامت"</string> <string name="description_target_soundon" msgid="30052466675500172">"تشغيل الصوت"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"بحث"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"مرر بسرعة لإلغاء التأمين."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"يمكنك توصيل سماعة رأس لسماع مفاتيح كلمة المرور عندما يتم نطقها."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"نقطة"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index b286a25..c78ecd9 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Дазваляе прыкладанням змяняць паварот экрана ў любы час. Не патрабуецца для звычайных прыкладанняў."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"змена хутк. перамяшч. ўказ."</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Дазваляе прыкладанням змяняць хуткасць курсору мышы або трэкпада ў любы час. Не патрабуецца для звычайных прыкладанняў."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"адправіць сігналы Linux да прыкладанняў"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Дазваляе прыкладанням запытваць адпраўку падаваемага сігнала для ўсiх пастаянных працэсаў."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"прымусіць прыкладанне працаваць заўсёды"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Усталяваць час"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Усталяваць дату"</string> <string name="date_time_set" msgid="5777075614321087758">"Задаць"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Гатова"</string> <string name="default_permission_group" msgid="2690160991405646128">"Па змаўчанні"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВАЕ: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Дазволу не патрабуецца"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Націсніце, каб адключыць адладку USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Выберыце метад уводу"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Наладзіць метады ўводу"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"кандыдат."</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Дадаць уліковы запіс"</string> <string name="choose_account_text" msgid="6303348737197849675">"Які ўліковы запіс вы жадаеце выкарыстоўваць?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Дадаць уліковы запіс"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Павялічыць"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Паменшыць"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Націсніце і ўтрымлівайце <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Правядзіце пальцам уверх, каб павялічыць, або ўніз, каб паменшыць."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Павялічыць лічбу хвілін."</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Паменшыць лічбу хвілін."</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Павялічыць лічбу гадзін."</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Паменшыць лічбу гадзін."</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Усталяваць час пасля паўдня"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Усталяваць час да паўдня"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Павялічыць лічбу месяца"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Паменшыць лічбу месяца"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Павялічыць лічбу дня"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Паменшыць лічбу дня"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Павялічыць лічбу года"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Паменшыць лічбу года"</string> <string name="checkbox_checked" msgid="7222044992652711167">"пастаўлены"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"не пастаўлены"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"абрана"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Апублікаваць з дапамогай"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Адправiць з дапамогай прыкладання <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Ручка для перасоўвання. Націсніце і ўтрымлівайце."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Правядзіце пальцам уверх, каб атрымаць <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Правядзіце пальцам уніз, каб атрымаць <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Правядзіце пальцам улева, каб атрымаць <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Правядзіце пальцам управа, каб атрымаць <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Разблакаваць"</string> <string name="description_target_camera" msgid="969071997552486814">"Камера"</string> <string name="description_target_silent" msgid="893551287746522182">"Ціхі рэжым"</string> <string name="description_target_soundon" msgid="30052466675500172">"Гук уключаны"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Пошук"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Прагартайце, каб разблакаваць."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Каб праслухаць паролi, падключыце гарнiтуру."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Кропка."</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 81a75bd..8bcbec3 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Разрешава на приложението да променя ориентацията на екрана по всяко време. Нормалните приложения би трябвало никога да не се нуждаят от това."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"промяна на скоростта на курсор"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Разрешава на приложението да променя скоростта на курсора на мишката или на тракпада по всяко време. Нормалните приложения би трябвало никога да не се нуждаят от това."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"изпращане на сигнали от Linux до приложенията"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Разрешава на приложението да подаде заявка предоставеният сигнал да се изпрати до всички постоянни процеси."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"задаване на постоянно изпълнение на приложението"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Задаване на часа"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Задаване на дата"</string> <string name="date_time_set" msgid="5777075614321087758">"Задаване"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Готово"</string> <string name="default_permission_group" msgid="2690160991405646128">"По подразбиране"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВО: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Не се изискват разрешения"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Докоснете, за да деактивирате отстраняването на грешки през USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Избор на метод на въвеждане"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Методи на въвеждане: Настройка"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Добавяне на профил"</string> <string name="choose_account_text" msgid="6303348737197849675">"Кой профил искате да използвате?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Добавяне на профил"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Увеличаване"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Намаляване"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Докоснете <xliff:g id="VALUE">%s</xliff:g> път/и и задръжте."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Плъзнете нагоре за увеличаване и надолу за намаляване."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Увеличаване на минутите"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Намаляване на минутите"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Увеличаване на часовете"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Намаляване на часовете"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Задаване на PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Задаване на AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Увеличаване на месеците"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Намаляване на месеците"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Увеличаване на дните"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Намаляване на дните"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Увеличаване на годините"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Намаляване на годините"</string> <string name="checkbox_checked" msgid="7222044992652711167">"отметнато"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"не е отметнато"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"избрано"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Споделяне със"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Споделяне със: <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Плъзгаща се дръжка. Докоснете и задръжте."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Плъзнете нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Плъзнете надолу за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Плъзнете наляво за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Плъзнете надясно за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Отключване"</string> <string name="description_target_camera" msgid="969071997552486814">"Камера"</string> <string name="description_target_silent" msgid="893551287746522182">"Тих режим"</string> <string name="description_target_soundon" msgid="30052466675500172">"Включване на звука"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Търсене"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Прокарайте пръст, за да отключите."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Включете слушалки, за да чуете изговарянето на клавишите за паролата."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Точка."</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 365e63a..fdae718 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permet que l\'aplicació canviï el gir de la pantalla en qualsevol moment. No s\'hauria de necessitar mai per a les aplicacions normals."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"canvi de velocitat del punter"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permet que l\'aplicació canviï la velocitat del punter del ratolí o del ratolí tàctil en qualsevol moment. No s\'hauria de necessitar mai per a les aplicacions normals."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"envia senyals Linux a les aplicacions"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permet que l\'aplicació sol·liciti que el senyal subministrat s\'enviï a tots els processos persistents."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"fes que l\'aplicació s\'executi sempre"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Estableix l\'hora"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establiment de data"</string> <string name="date_time_set" msgid="5777075614321087758">"Defineix"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Fet"</string> <string name="default_permission_group" msgid="2690160991405646128">"Predeterminat"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOU: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"No cal cap permís"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca-ho per desactivar la depuració USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Selecció de mètodes d\'introducció"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Configura els mètodes d\'entrada"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Addició d\'un compte"</string> <string name="choose_account_text" msgid="6303348737197849675">"Quin compte vols utilitzar?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Afegeix un compte"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Incrementa"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Redueix"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén premut <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Fes lliscar el dit cap amunt per incrementar i cap avall per disminuir."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Fes augmentar el minut"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Fes disminuir el minut"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Fes augmentar l\'hora"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Fes disminuir l\'hora"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Estableix com a p. m."</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Estableix com a a. m."</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Fes augmentar el mes"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Fes disminuir el mes"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Fes augmentar el dia"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Fes disminuir el dia"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Fes augmentar l\'any"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Fes disminuir l\'any"</string> <string name="checkbox_checked" msgid="7222044992652711167">"marcat"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"no marcat"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"seleccionat"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Comparteix amb"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Comparteix amb <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Llisca el dit. Mantén premut."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Fes lliscar el dit cap amunt per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Fes lliscar el dit cap avall per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Fes lliscar el dit cap a l\'esquerra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Fes lliscar el dit cap a la dreta per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Desbloqueja"</string> <string name="description_target_camera" msgid="969071997552486814">"Càmera"</string> <string name="description_target_silent" msgid="893551287746522182">"Silenci"</string> <string name="description_target_soundon" msgid="30052466675500172">"Activa el so"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Cerca"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Llisca el dit per desbloquejar."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Connecta un auricular per escoltar les claus de la contrasenya en veu alta."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punt."</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index d95feaa..98b5771 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Umožňuje aplikaci kdykoli změnit otočení obrazovky. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"změna rychlosti kurzoru"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Umožňuje aplikaci kdykoli změnit rychlost ukazatele myši nebo touchpadu. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"odeslání signálů systému Linux aplikacím"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Umožňuje aplikaci vyžádat zaslání poskytnutého signálu všem trvalým procesům."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"trvalé spuštění aplikace"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastavení času"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavení data"</string> <string name="date_time_set" msgid="5777075614321087758">"Nastavit"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Hotovo"</string> <string name="default_permission_group" msgid="2690160991405646128">"Výchozí"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVÉ: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nejsou vyžadována žádná oprávnění"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotykem zakážete ladění USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Vybrat metodu vstupu"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Nastavit metody vstupu"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Přidat účet"</string> <string name="choose_account_text" msgid="6303348737197849675">"Který účet chcete použít?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Přidat účet"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Zvýšit"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Snížit"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> dotkněte se a podržte."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Chcete-li hodnotu zvýšit, přijeďte prstem nahoru, chcete-li hodnotu snížit, přejeďte prstem dolů."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Přidat minutu"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Ubrat minutu"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Přidat hodinu"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Ubrat hodinu"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nastavit odp."</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nastavit dop."</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Přidat měsíc"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Ubrat měsíc"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Přidat den"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Ubrat den"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Přidat rok"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Ubrat rok"</string> <string name="checkbox_checked" msgid="7222044992652711167">"zaškrtnuto"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nezaškrtnuto"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"Vybráno"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Sdílet s"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Sdílet s aplikací <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Posuvník. Dotkněte se a podržte."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Přejeďte prstem nahoru: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string> + <string name="description_direction_down" msgid="5087739728639014595">"Přejeďte prstem dolů: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string> + <string name="description_direction_left" msgid="7207478719805562165">"Přejeďte prstem doleva: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string> + <string name="description_direction_right" msgid="8034433242579600980">"Přejeďte prstem doprava: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string> <string name="description_target_unlock" msgid="2228524900439801453">"Odemknout"</string> <string name="description_target_camera" msgid="969071997552486814">"Fotoaparát"</string> <string name="description_target_silent" msgid="893551287746522182">"Tichý"</string> <string name="description_target_soundon" msgid="30052466675500172">"Zapnout zvuk"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Vyhledávání"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Odemknete posunutím prstu."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Chcete-li slyšet, které klávesy jste při zadávání hesla stiskli, připojte sluchátka."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Tečka."</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 3560e3d..a3c7474 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Tillader, at appen kan ændre skærmretningen på et hvilket som helst tidspunkt. Bør aldrig være nødvendigt for almindelige apps."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ændre markørens hastighed"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Tillader, at appen til enhver tid kan ændre musemarkørens hastighed. Bør aldrig være nødvendigt for normale apps."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"sende Linux-signaler til apps"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Tillader, at appen kan anmode om, at det leverede signal sendes til alle vedholdende processer."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"sørge for, at appen altid kører"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Angiv tidspunkt"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angiv dato"</string> <string name="date_time_set" msgid="5777075614321087758">"Angiv"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Udført"</string> <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NYHED! "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Der kræves ingen tilladelser"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Tryk for at deaktivere USB-fejlretning."</string> <string name="select_input_method" msgid="4653387336791222978">"Vælg inputmetode"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Konfigurer inputmetoder"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Tilføj en konto"</string> <string name="choose_account_text" msgid="6303348737197849675">"Hvilken konto vil du bruge?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Tilføj konto"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Højere"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Lavere"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Tryk <xliff:g id="VALUE">%s</xliff:g> gange, og hold inde."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Glid op for at øge og ned for at mindske."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Forøg minuttal"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Sænk minuttal"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Forøg timetal"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Sænk timetal"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Indstil PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Indstil AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Senere måned"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Tidligere måned"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Senere dag"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Tidligere dag"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Senere år"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Tidligere år"</string> <string name="checkbox_checked" msgid="7222044992652711167">"markeret"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"ikke markeret"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"udvalgt"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Del med"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Del med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Glidende håndtag. Tryk og hold nede."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Glid op for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Glid ned for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Glid til venstre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Glid til højre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Lås op"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Lydløs"</string> <string name="description_target_soundon" msgid="30052466675500172">"Lyd slået til"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Søgning"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glid hurtigt henover for at låse op."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Tilslut et headset for at høre tasterne blive læst højt ved angivelse af adgangskode."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punktum."</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 66b87c0..ae88920 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Ermöglicht der App, die Bildschirmdrehung jederzeit zu ändern. Sollte nie für normale Apps benötigt werden."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Zeigergeschwindigkeit ändern"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Ermöglicht der App, jederzeit die Geschwindigkeit des Maus- bzw. Touchpad-Zeigers zu ändern. Sollte nie für normale Apps benötigt werden."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linux-Signale an Apps senden"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Ermöglicht der App, das Senden des gelieferten Signals an alle andauernden Prozesse zu fordern"</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"App permanent ausführen"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Uhrzeit festlegen"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum festlegen"</string> <string name="date_time_set" msgid="5777075614321087758">"Speichern"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Fertig"</string> <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"Neu: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Keine Berechtigungen erforderlich"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Zum Deaktivieren von USB-Debugging tippen"</string> <string name="select_input_method" msgid="4653387336791222978">"Eingabemethode wählen"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Eingabemethoden einrichten"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"Kandidaten"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Konto hinzufügen"</string> <string name="choose_account_text" msgid="6303348737197849675">"Welches Konto möchten Sie verwenden?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Konto hinzufügen"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Verlängern"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Verringern"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> berühren und gedrückt halten"</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Zum Verlängern nach oben und zum Verringern nach unten schieben"</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Minuten verlängern"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Minuten verringern"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Stunden verlängern"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Stunden verringern"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Zeit festlegen"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Zeit festlegen"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Monat verlängern"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Monat verringern"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Tag verlängern"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Tag verringern"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Jahr verlängern"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Jahr verringern"</string> <string name="checkbox_checked" msgid="7222044992652711167">"Aktiviert"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"Nicht aktiviert"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"Ausgewählt"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Teilen mit"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Mit <xliff:g id="APPLICATION_NAME">%s</xliff:g> teilen"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Schieberegler: Berühren und halten"</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach oben schieben"</string> + <string name="description_direction_down" msgid="5087739728639014595">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach unten schieben"</string> + <string name="description_direction_left" msgid="7207478719805562165">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach links schieben"</string> + <string name="description_direction_right" msgid="8034433242579600980">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach rechts schieben"</string> <string name="description_target_unlock" msgid="2228524900439801453">"Entsperren"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Lautlos"</string> <string name="description_target_soundon" msgid="30052466675500172">"Ton ein"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Suche"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Zum Entsperren den Finger über den Bildschirm ziehen"</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Schließen Sie ein Headset an, um das Passwort gesprochen zu hören."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 942a40a..ce49a84 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Επιτρέπει στην εφαρμογή την αλλαγή της περιστροφής της οθόνης ανά πάσα στιγμή. Δεν απαιτείται για συνήθεις εφαρμογές."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"αλλαγή ταχύτητας δείκτη"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Επιτρέπει στην εφαρμογή την αλλαγή της ταχύτητας του δείκτη του ποντικιού ή της επιφάνειας αφής ανά πάσα στιγμή. Δεν πρέπει να χρησιμοποιείται από συνήθεις εφαρμογές."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"αποστολή σημάτων Linux σε εφαρμογές"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Επιτρέπει στην εφαρμογή την αποστολή αιτήματος για την αποστολή του παρεχόμενου σήματος σε όλες τις υπάρχουσες διαδικασίες."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"να εκτελείται συνεχώς η εφαρμογή"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ρύθμιση ώρας"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ορισμός ημερομηνίας"</string> <string name="date_time_set" msgid="5777075614321087758">"Ορισμός"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Τέλος"</string> <string name="default_permission_group" msgid="2690160991405646128">"Προεπιλεγμένο"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"ΝΕΟ: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Δεν απαιτούνται άδειες"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Αγγίξτε για απενεργοποίηση του εντοπισμού σφαλμάτων USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Επιλογή μεθόδου εισόδου"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Ρύθμιση μεθόδων εισαγωγής"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"υποψήφιοι"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Προσθήκη λογαριασμού"</string> <string name="choose_account_text" msgid="6303348737197849675">"Ποιον λογαριασμό θέλετε να χρησιμοποιήσετε;"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Προσθήκη λογαριασμού"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Αύξηση"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Μείωση"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Πατήστε παρατεταμένα το <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Πραγματοποιήστε κύλιση προς τα πάνω για αύξηση και προς τα κάτω για μείωση."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Αύξηση λεπτού"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Μείωση λεπτού"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Αύξηση ώρας"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Μείωση ώρας"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Ορισμός ΜΜ"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Ορισμός ΠΜ"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Αύξηση μήνα"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Μείωση μήνα"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Αύξηση ημέρας"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Μείωση ημέρας"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Αύξηση έτους"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Μείωση έτους"</string> <string name="checkbox_checked" msgid="7222044992652711167">"ελέγχθηκε"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"δεν επιλέχθηκε"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"επιλεγμένο"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Κοινή χρήση με"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Κοινή χρήση με <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Στοιχείο χειρισμού με δυνατότητα ολίσθησης. Αγγίξτε και πατήστε παρατεταμένα."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Κύλιση προς τα επάνω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Κύλιση προς τα κάτω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Κύλιση προς τα αριστερά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Κύλιση προς τα δεξιά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Ξεκλείδωμα"</string> <string name="description_target_camera" msgid="969071997552486814">"Φωτογραφική μηχανή"</string> <string name="description_target_silent" msgid="893551287746522182">"Αθόρυβο"</string> <string name="description_target_soundon" msgid="30052466675500172">"Ενεργοποίηση ήχου"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Αναζήτηση"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Σύρετε για ξεκλείδωμα."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Συνδέστε ακουστικά για να ακούσετε τα πλήκτρα του κωδικού πρόσβασης να εκφωνούνται."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Τελεία."</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index fa767ff..38b69fe 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Allows the app to change the rotation of the screen at any time. Should never be needed for normal apps."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"change pointer speed"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Allows the app to change the mouse or touch pad pointer speed at any time. Should never be needed for normal apps."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"send Linux signals to apps"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Allows the app to request that the supplied signal be sent to all persistent processes."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"make app always run"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string> <string name="date_time_set" msgid="5777075614321087758">"Set"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Done"</string> <string name="default_permission_group" msgid="2690160991405646128">"Default"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NEW: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"No permission required"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Touch to disable USB debugging."</string> <string name="select_input_method" msgid="4653387336791222978">"Choose input method"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Set up input methods"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidates"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Add an account"</string> <string name="choose_account_text" msgid="6303348737197849675">"Which account do you want to use?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Add account"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Increase"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Decrease"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> touch and hold."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Slide up to increase and down to decrease."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Increase minute"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Decrease minute"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Increase hour"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Decrease hour"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Set p.m."</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Set a.m."</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Increase month"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Decrease month"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Increase day"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Decrease day"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Increase year"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Decrease year"</string> <string name="checkbox_checked" msgid="7222044992652711167">"ticked"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"not ticked"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"selected"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Share with"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Share with <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Sliding handle. Touch & hold."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Slide down for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Slide right for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Unlock"</string> <string name="description_target_camera" msgid="969071997552486814">"Camera"</string> <string name="description_target_silent" msgid="893551287746522182">"Silent"</string> <string name="description_target_soundon" msgid="30052466675500172">"Sound on"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Search"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Swipe to unlock."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Plug in a headset to hear password keys spoken."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 5c7b782..d400734 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite que la aplicación cambie la rotación de la pantalla en cualquier momento. Las aplicaciones normales no deberían necesitar este permiso."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"cambiar velocidad del puntero"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite que la aplicación cambie la velocidad del puntero del mouse o el trackpad en cualquier momento. Las aplicaciones normales no deben utilizar este permiso."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"enviar señales de Linux a las aplicaciones"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite que la aplicación solicite que la señal suministrada se envíe a todos los procesos persistentes."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"hacer que la aplicación se ejecute siempre"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Configurar hora"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Configurar fecha"</string> <string name="date_time_set" msgid="5777075614321087758">"Establecer"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Listo"</string> <string name="default_permission_group" msgid="2690160991405646128">"Predeterminado"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NUEVO: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"No se requieren permisos"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toca para desactivar la depuración de USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Selecciona el método de introducción"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Configurar métodos de introducción"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Agregar una cuenta"</string> <string name="choose_account_text" msgid="6303348737197849675">"¿Qué cuenta quieres usar?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Agregar una cuenta"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Aumentar"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Reducir"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén presionado <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Desliza el dedo hacia arriba para aumentar los valores y hacia abajo para reducirlos."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Aumentar minutos"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Reducir minutos"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Aumentar hora"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Reducir hora"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Establecer p.m."</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Establecer a.m."</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Aumentar mes"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Reducir mes"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Aumentar día"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reducir día"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar año"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reducir año"</string> <string name="checkbox_checked" msgid="7222044992652711167">"marcado"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"no marcado"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"seleccionado"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Compartir con"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartir con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Mantén presionado el controlador deslizante."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Desliza el dedo hacia abajo para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Desliza el dedo hacia la derecha para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Desbloquear"</string> <string name="description_target_camera" msgid="969071997552486814">"Cámara"</string> <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string> <string name="description_target_soundon" msgid="30052466675500172">"Sonido activado"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Buscar"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Desliza el dedo para desbloquear."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecta un auricular para escuchar las contraseñas."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index e863aba..6852184 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite que la aplicación cambie la rotación de la pantalla en cualquier momento. Las aplicaciones normales no deberían necesitar este permiso."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"cambiar velocidad del puntero"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite que la aplicación modifique la velocidad del puntero del ratón o del trackpad en cualquier momento. Las aplicaciones normales no deberían necesitar este permiso."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"enviar señales Linux a aplicaciones"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite que la aplicación solicite que la señal suministrada se envíe a todos los procesos persistentes."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"hacer que la aplicación se ejecute siempre"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Establecer hora"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establecer fecha"</string> <string name="date_time_set" msgid="5777075614321087758">"Establecer"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Listo"</string> <string name="default_permission_group" msgid="2690160991405646128">"Predeterminado"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NUEVO:"</font></string> <string name="no_permissions" msgid="7283357728219338112">"No es necesario ningún permiso"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Tocar para inhabilitar la depuración USB"</string> <string name="select_input_method" msgid="4653387336791222978">"Seleccionar método de introducción"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Ajustar métodos de introducción"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Añadir una cuenta"</string> <string name="choose_account_text" msgid="6303348737197849675">"¿Qué cuenta quieres usar?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Añadir cuenta"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Aumentar"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Reducir"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén pulsado <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Desliza el dedo hacia arriba para aumentar y hacia abajo para disminuir."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Aumentar minutos"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Reducir minutos"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Aumentar horas"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Reducir horas"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Establecer p.m."</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Establecer a.m."</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Aumentar mes"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Reducir mes"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Aumentar días"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reducir días"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar año"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reducir año"</string> <string name="checkbox_checked" msgid="7222044992652711167">"seleccionado"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"no seleccionado"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"seleccionado"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Compartir con"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartir con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Mantén pulsado el icono de desbloqueo y deslízalo."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Desliza el dedo hacia abajo para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Desliza el dedo hacia la derecha para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Desbloquear"</string> <string name="description_target_camera" msgid="969071997552486814">"Cámara"</string> <string name="description_target_silent" msgid="893551287746522182">"Silencio"</string> <string name="description_target_soundon" msgid="30052466675500172">"Sonido activado"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Buscar"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Desliza el dedo para desbloquear."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecta un auricular para escuchar las contraseñas."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 5303a13..737ab21 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Võimaldab rakendusel muuta ekraani pööramist mis tahes ajal. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"kursorikiiruse muutmine"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Võimaldab rakendusel muuta igal ajal hiire- või puutepadjakursori kiirust. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linuxi signaalide saatmine rakendustele"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Võimaldab rakendusel taotleda edastatud signaali saatmist kõigile püsiprotsessidele."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"Rakenduste pidev töös hoidmine"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Kellaaja määramine"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Kuupäeva määramine"</string> <string name="date_time_set" msgid="5777075614321087758">"Määra"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Valmis"</string> <string name="default_permission_group" msgid="2690160991405646128">"Vaikimisi"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"UUS: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Lube pole vaja"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Puudutage USB-silumise keelamiseks."</string> <string name="select_input_method" msgid="4653387336791222978">"Valige sisestusmeetod"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Seadista sisestusmeetodid"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaadid"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Konto lisamine"</string> <string name="choose_account_text" msgid="6303348737197849675">"Millist kontot soovite kasutada?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Lisa konto"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Suurendamine"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Vähendamine"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> puudutage ja hoidke."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Suurendamiseks lohistage üles, vähendamiseks alla."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Minutite suurendamine"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Minutite vähendamine"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Tundide suurendamine"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Tundide vähendamine"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM-i seadmine"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM-i seadmine"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Kuu suurendamine"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Kuu vähendamine"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Päeva suurendamine"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Päeva vähendamine"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aasta suurendamine"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Aasta vähendamine"</string> <string name="checkbox_checked" msgid="7222044992652711167">"märgitud"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"pole märgitud"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"valitud"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Jaga:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Jaga rakendusega <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Libistamispide. Puudutage ja hoidke all."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Lohistage üles: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Lohistage alla: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Lohistage vasakule: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Lohistage paremale: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Luku avamine"</string> <string name="description_target_camera" msgid="969071997552486814">"Kaamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Hääletu"</string> <string name="description_target_soundon" msgid="30052466675500172">"Heli on sees"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Otsing"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Avamiseks tõmmake sõrmega."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Paroolide kuulamiseks ühendage peakomplekt."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 92cb595..80b273b 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"به برنامه اجازه میدهد تا چرخش صفحه را هر وقت بخواهد تغییر دهد. برای برنامههای عادی نیاز نیست."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"تغییر سرعت اشاره گر"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"به برنامه اجازه میدهد تا سرعت ماوس و پد کنترل را هر وقت خواست تغییر دهد. برای برنامههای عادی نیاز نیست."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"ارسال سیگنالهای Linux به برنامهها"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"به برنامه اجازه میدهد تا درخواست کند سیگنال ارائه شده به همه مراحل دائم ارسال شود."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"همیشه برنامه اجرا شود"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"تنظیم زمان"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ تنظیم"</string> <string name="date_time_set" msgid="5777075614321087758">"تنظیم"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"انجام شد"</string> <string name="default_permission_group" msgid="2690160991405646128">"پیش فرض"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"جدید: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"مجوزی لازم نیست"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"غیرفعال کردن اشکال زدایی USB را لمس کنید."</string> <string name="select_input_method" msgid="4653387336791222978">"انتخاب روش ورودی"</string> <string name="configure_input_methods" msgid="9091652157722495116">"تنظیم روشهای ورودی"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"داوطلبین"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"افزودن یک حساب"</string> <string name="choose_account_text" msgid="6303348737197849675">"کدام حساب را میخواهید استفاده کنید؟"</string> <string name="add_account_button_label" msgid="3611982894853435874">"افزودن حساب"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"افزایش"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"کاهش"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> لمس کرده و نگه دارید."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"برای افزایش به بالا بلغزانید و برای کاهش به پایین بلغزانید."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"افزایش دقیقه"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"کاهش دقیقه"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"افزایش ساعت"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"کاهش ساعت"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"تنظیم ب.ظ"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"تنظیم ق.ظ"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"افزایش ماه"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"کاهش ماه"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"افزایش روز"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"کاهش روز"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"افزایش سال"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"کاهش سال"</string> <string name="checkbox_checked" msgid="7222044992652711167">"علامت زده"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"بدون علامت"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"انتخاب شد"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"اشتراکگذاری با"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"اشتراکگذاری با <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"اهرم کنترل حرکت. لمس کرده و نگهدارید."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"لغزاندن به بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"لغزاندن به پایین برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"لغزاندن به چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"لغزاندن به راست برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"بازکردن قفل"</string> <string name="description_target_camera" msgid="969071997552486814">"دوربین"</string> <string name="description_target_silent" msgid="893551287746522182">"ساکت"</string> <string name="description_target_soundon" msgid="30052466675500172">"صدا روشن"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"جستجو"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"برای بازگشایی قفل، بلغزانید."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"برای شنیدن کلیدهای گذرواژه که با صدای بلند خوانده میشوند، هدست را وصل کنید."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"نقطه."</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index e3db295..f011ec3 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Antaa sovelluksen muuttaa näytön kiertoa milloin tahansa. Ei tavallisten sovellusten käyttöön."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"muuta osoittimen nopeutta"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Antaa sovelluksen muuttaa hiiren tai kosketuslevyn osoittimen nopeutta milloin tahansa. Ei tavallisten sovellusten käyttöön."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linux-signaalien lähettäminen sovelluksille"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Antaa sovelluksen pyytää, että tarjottu signaali lähetetään kaikille käynnissä oleville prosesseille."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"sovelluksen asettaminen aina käynnissä olevaksi"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Aseta aika"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Aseta päivämäärä"</string> <string name="date_time_set" msgid="5777075614321087758">"Aseta"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Valmis"</string> <string name="default_permission_group" msgid="2690160991405646128">"Oletus"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"UUTTA: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Lupia ei tarvita"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Poista USB-vianetsintä käytöstä koskettamalla tätä."</string> <string name="select_input_method" msgid="4653387336791222978">"Valitse syöttötapa"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Määritä syöttötavat"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaatit"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Lisää tili"</string> <string name="choose_account_text" msgid="6303348737197849675">"Mitä tiliä haluat käyttää?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Lisää tili"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Lisää"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Vähennä"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> kosketa pitkään."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Lisää tai vähennä arvoa liu\'uttamalla ylös tai alas."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Lisää minuuttien määrää."</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Vähennä minuuttien määrää."</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Lisää tuntien määrää."</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Vähennä tuntien määrää."</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Aseta ip"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Aseta ap"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Lisää kuukausien määrää."</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Vähennä kuukausien määrää."</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Lisää päivien määrää."</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Vähennä päivien määrää."</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Lisää vuosien määrää."</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Vähennä vuosien määrää."</string> <string name="checkbox_checked" msgid="7222044992652711167">"valittu"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"ei valittu"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"valittu"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Jaa seuraavien kanssa:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Jaa sovelluksessa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Liukuva valitsin. Kosketa pitkään."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Liu\'uta ylös ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Liu\'uta alas ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Liu\'uta vasemmalle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Liu\'uta oikealle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Poista lukitus"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Äänetön"</string> <string name="description_target_soundon" msgid="30052466675500172">"Ääni käytössä"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Haku"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Poista lukitus liu\'uttamalla."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Liitä kuulokkeet kuullaksesi, mitä näppäimiä painat kirjoittaessasi salasanaa."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Piste."</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 60eed61..7c78654 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permet à l\'application de changer l\'orientation de l\'écran à tout moment. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"changer la vitesse du pointeur"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permet à l\'application de modifier à tout moment la vitesse du pointeur de la souris ou du pavé tactile. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"envoyer des signaux Linux aux applications"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permet à l\'application de demander que le signal fourni soit envoyé à tous les processus persistants."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"exécuter l\'application en continu"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Définir l\'heure"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Définir la date"</string> <string name="date_time_set" msgid="5777075614321087758">"Définir"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"OK"</string> <string name="default_permission_group" msgid="2690160991405646128">"Par défaut"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOUVEAU"</font>" :"</string> <string name="no_permissions" msgid="7283357728219338112">"Aucune autorisation requise"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Appuyez pour désactiver le débogage USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Sélectionnez le mode de saisie"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Configurer les modes de saisie"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Ajouter un compte"</string> <string name="choose_account_text" msgid="6303348737197849675">"Quel compte souhaitez-vous utiliser ?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Ajouter un compte"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Augmenter"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Diminuer"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> appuyez de manière prolongée."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Faites glisser vers le haut pour augmenter et vers le bas pour diminuer."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Minute suivante"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Minute précédente"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Heure suivante"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Heure précédente"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Définir la valeur PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Définir la valeur AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Mois suivant"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Mois précédent"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Jour suivant"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Jour précédent"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Année suivante"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Année précédente"</string> <string name="checkbox_checked" msgid="7222044992652711167">"coché"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"non coché"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"sélectionné"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Partager avec"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Partager avec <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Poignée coulissante. Appuyez de manière prolongée."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Faites glisser vers le haut pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Faites glisser vers le bas pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Faites glisser vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Faites glisser vers la droite pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Déverrouiller"</string> <string name="description_target_camera" msgid="969071997552486814">"Appareil photo"</string> <string name="description_target_silent" msgid="893551287746522182">"Mode silencieux"</string> <string name="description_target_soundon" msgid="30052466675500172">"Son activé"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Rechercher"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Faites glisser votre doigt pour déverrouiller l\'appareil."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Branchez des écouteurs pour entendre l\'énoncé des touches lors de la saisie du mot de passe."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Point."</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 5120648..1ee3d03 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"एप्लिकेशन को किसी भी समय स्क्रीन का रोटेशन बदलने देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यक नहीं होना चाहिए."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"सूचक गति बदलें"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"एप्लिकेशन को माउस या ट्रैकपैड सूचक गति को किसी भी समय बदलने देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यक नहीं होना चाहिए."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"एप्लिकेशन को Linux सिग्नल भेजें"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"एप्लिकेशन को यह अनुरोध करने देता है कि दिया गया सिग्नल सभी जारी प्रक्रियाओं को भेजा जाए."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"एप्लिकेशन को हमेशा चलने वाला बनाएं"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"समय सेट करें"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"दिनांक सेट करें"</string> <string name="date_time_set" msgid="5777075614321087758">"सेट करें"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"पूर्ण"</string> <string name="default_permission_group" msgid="2690160991405646128">"डिफ़ॉल्ट"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"नया: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"किसी अनुमति की आवश्यकता नहीं है"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB डीबग करना अक्षम करने के लिए स्पर्श करें."</string> <string name="select_input_method" msgid="4653387336791222978">"इनपुट पद्धति चुनें"</string> <string name="configure_input_methods" msgid="9091652157722495116">"इनपुट पद्धतियां सेट करें"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"उम्मीदवार"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"कोई खाता जोड़ें"</string> <string name="choose_account_text" msgid="6303348737197849675">"आप कौन-सा खाता उपयोग करना चाहते हैं?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"खाता जोड़ें"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"बढ़ाएं"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"कम करें"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> को स्पर्श करके रखें."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"बढ़ाने के लिए ऊपर और कम करने के लिए नीचे स्लाइड करें."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"मिनट बढ़ाएं"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"मिनट कम करें"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"घंटे बढ़ाएं"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"घंटे कम करें"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"सायं सेट करें"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"प्रात: सेट करें"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"माह बढ़ाएं"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"माह कम करें"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"दिन बढ़ाएं"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"दिन कम करें"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"वर्ष बढ़ाएं"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"वर्ष कम करें"</string> <string name="checkbox_checked" msgid="7222044992652711167">"चेक किया गया"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"चेक नहीं किया गया"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"चयनित"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"इसके साथ साझा करें:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> के साथ साझा करें"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"स्लाइडिंग हैंडल. स्पर्श करके रखें."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्लाइड करें."</string> + <string name="description_direction_down" msgid="5087739728639014595">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए नीचे स्लाइड करें."</string> + <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं स्लाइड करें."</string> + <string name="description_direction_right" msgid="8034433242579600980">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए दाएं स्लाइड करें."</string> <string name="description_target_unlock" msgid="2228524900439801453">"अनलॉक करें"</string> <string name="description_target_camera" msgid="969071997552486814">"कैमरा"</string> <string name="description_target_silent" msgid="893551287746522182">"मौन"</string> <string name="description_target_soundon" msgid="30052466675500172">"ध्वनि चालू करें"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"खोजें"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"अनलॉक करने के लिए स्वाइप करें."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"बोली गईं पासवर्ड कुंजियां सुनने के लिए हेडसेट प्लग इन करें."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"बिंदु."</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index b00cbab..0023310 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Omogućuje aplikaciji promjenu rotacije zaslona u bilo kojem trenutku. Ne bi smjelo biti potrebno za normalne aplikacije."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"promjena brzine pokazivača"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Omogućuje aplikaciji promjenu brzine miša ili dodirne pločice. Ne bi smjelo biti potrebno za normalne aplikacije."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"slanje Linux signala aplikacijama"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Aplikaciji omogućuje zahtijevanje da isporučeni signal bude poslan na sve trajne procese."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"trajni rad aplikacije"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Postavljanje vremena"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Postavi datum"</string> <string name="date_time_set" msgid="5777075614321087758">"Postavi"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Gotovo"</string> <string name="default_permission_group" msgid="2690160991405646128">"Zadano"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVO: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nije potrebno dopuštenje"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dodirnite da biste onemogućili rješavanje programske pogreške na USB-u."</string> <string name="select_input_method" msgid="4653387336791222978">"Odabir načina unosa"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Postavljanje načina unosa"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Dodajte račun"</string> <string name="choose_account_text" msgid="6303348737197849675">"Koji račun želite upotrijebiti?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj račun"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Povećavanje"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Smanjivanje"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> pritisnite i držite."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Kliznite prema gore za povećavanje i prema dolje za smanjivanje."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Povećanje minuta"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Smanjenje minuta"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Povećanje sati"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Smanjenje sati"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Postavi PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Postavi AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Povećanje mjeseca"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Smanjenje mjeseca"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Povećanje dana"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Smanjenje dana"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Povećanje godine"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Smanjenje godine"</string> <string name="checkbox_checked" msgid="7222044992652711167">"označeno"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nije označeno"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"odabran"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Dijeljenje sa"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Dijeli s aplikacijom <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Klizna ručka. Dodirnite i držite."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Kliznite prema gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Kliznite prema dolje za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Kliznite lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Kliznite desno za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Otključaj"</string> <string name="description_target_camera" msgid="969071997552486814">"Fotoaparat"</string> <string name="description_target_silent" msgid="893551287746522182">"Bešumno"</string> <string name="description_target_soundon" msgid="30052466675500172">"Zvuk je uključen"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Prijeđite prstima da biste otključali."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Priključite slušalice kako biste čuli izgovaranje tipki zaporke."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Točka."</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 25a8d2a..4ae52d5 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Lehetővé teszi az alkalmazás számára a képernyő elforgatásának bármikori módosítását. A normál alkalmazásoknak erre soha nincs szüksége."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"mutató sebességének módosítása"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Lehetővé teszi az alkalmazás számára, hogy bármikor módosítsa az egér vagy az érintőpad mutatójának sebességét. Normál alkalmazásoknak soha nem lehet rá szükségük."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linux-jelek küldése az alkalmazásoknak"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Lehetővé teszi az alkalmazás számára, hogy a megadott jelet elküldje az összes állandó folyamatnak."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"az alkalmazás állandó futtatása"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Idő beállítása"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Dátum beállítása"</string> <string name="date_time_set" msgid="5777075614321087758">"Beállítás"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Kész"</string> <string name="default_permission_group" msgid="2690160991405646128">"Alapértelmezett"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"ÚJ: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nincs szükség engedélyre"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Érintse meg az USB hibakeresés kikapcsolásához."</string> <string name="select_input_method" msgid="4653387336791222978">"Beviteli mód kiválasztása"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Beviteli módok beállítása"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"jelöltek"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Fiók hozzáadása"</string> <string name="choose_account_text" msgid="6303348737197849675">"Melyik fiókot szeretné használni?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Fiók hozzáadása"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Növelés"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Csökkentés"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> érintse meg és tartsa lenyomva."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"A növeléshez csúsztassa felfelé, a csökkentéshez pedig lefelé."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Perc értékének növelése"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Perc értékének csökkentése"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Óra értékének növelése"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Óra értékének csökkentése"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Állítsa du. értékre"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Állítsa de. értékre"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Hónap értékének növelése"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Hónap értékének csökkentése"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Dátum értékének növelése"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Dátum értékének csökkentése"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Év értékének növelése"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Év értékének csökkentése"</string> <string name="checkbox_checked" msgid="7222044992652711167">"bejelölve"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nincs bejelölve"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"bejelölve"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Megosztás a következővel:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Ossza meg a következő alkalmazással: <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Csúsztatható fogantyú. Érintse meg és tartsa."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa felfelé."</string> + <string name="description_direction_down" msgid="5087739728639014595">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa lefelé."</string> + <string name="description_direction_left" msgid="7207478719805562165">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa balra."</string> + <string name="description_direction_right" msgid="8034433242579600980">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa jobbra."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Feloldás"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Némítás"</string> <string name="description_target_soundon" msgid="30052466675500172">"Hang bekapcsolása"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Keresés"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"A feloldásához húzza végig az ujját."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Csatlakoztasson egy fülhallgatót, ha hallani szeretné a jelszó betűit felolvasva."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Pont."</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 0fa59fc..bd6294b 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Mengizinkan apl mengubah rotasi layar kapan saja. Tidak pernah dibutuhkan oleh apl normal."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ubah kecepatan penunjuk"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Mengizinkan apl mengubah kecepatan mouse atau pointer trackpad kapan saja. Tidak pernah diperlukan oleh apl normal."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"mengirim sinyal Linux ke apl"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Mengizinkan apl meminta agar sinyal yang disediakan dikirim ke semua proses yang ada."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"membuat apl selalu berjalan"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Setel waktu"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setel tanggal"</string> <string name="date_time_set" msgid="5777075614321087758">"Setel"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Selesai"</string> <string name="default_permission_group" msgid="2690160991405646128">"Default"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"BARU: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Tidak perlu izin"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk menonaktifkan debugging USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Pilih metode masukan"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Menyiapkan metode masukan"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Tambahkan akun"</string> <string name="choose_account_text" msgid="6303348737197849675">"Akun mana yang ingin Anda gunakan?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Tambahkan akun"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Tambah"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Kurangi"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> sentuh dan tahan."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Geser ke atas untuk menambah dan ke bawah untuk mengurangi."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Tambah menit"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Kurangi menit"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Tambah jam"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Kurangi jam"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Menyetel PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Setel AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Tambah bulan"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Kurangi bulan"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Tambah hari"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Kurangi hari"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Tambah tahun"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Kurangi tahun"</string> <string name="checkbox_checked" msgid="7222044992652711167">"dicentang"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"tidak diperiksa"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"dipilih"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Berbagi dengan"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Berbagi dengan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Gagang geser. Sentuh & tahan."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Geser ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Geser ke bawah untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Geser ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Geser ke kanan untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Membuka gembok"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Senyap"</string> <string name="description_target_soundon" msgid="30052466675500172">"Suara hidup"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Telusuri"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Gesek untuk membuka kunci."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pasang headset untuk mendengar tombol sandi yang diucapkan."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Titik."</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index fc9ab19..ae52c62 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Consente all\'applicazione di cambiare la rotazione dello schermo in qualsiasi momento. Non dovrebbe mai essere necessario per le normali applicazioni."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"cambio velocità del puntatore"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Consente all\'applicazione di modificare la velocità del puntatore del mouse o del trackpad in qualsiasi momento. Non dovrebbe mai essere necessaria per le applicazioni normali."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"invio segnali Linux alle applicazioni"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Consente all\'applicazione di richiedere l\'invio del segnale fornito a tutti i processi persistenti."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"esecuzione permanente delle applicazioni"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Imposta ora"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Imposta data"</string> <string name="date_time_set" msgid="5777075614321087758">"Imposta"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Fine"</string> <string name="default_permission_group" msgid="2690160991405646128">"Predefinito"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NUOVA: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nessuna autorizzazione richiesta"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Tocca per disattivare il debug USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Scegli il metodo di immissione"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Configura metodi di immissione"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidati"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Aggiungi un account"</string> <string name="choose_account_text" msgid="6303348737197849675">"Quale account vuoi usare?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Aggiungi account"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Aumenta"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Riduci"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Tocca e tieni premuto il numero <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Scorri verso l\'alto per aumentare il valore e verso il basso per diminuirlo."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Aumenta minuti"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Riduci minuti"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Aumenta ore"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Riduci ore"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Imposta PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Imposta AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Aumenta mese"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Riduci mese"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Aumenta giorno"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Riduci giorno"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumenta anno"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Riduci anno"</string> <string name="checkbox_checked" msgid="7222044992652711167">"selezionata"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"non selezionato"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"selezionato"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Condividi con"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Condividi con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Maniglia scorrevole. Tocca e tieni premuto."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Su per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Giù per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"A sinistra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"A destra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Sblocca"</string> <string name="description_target_camera" msgid="969071997552486814">"Fotocamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Silenzioso"</string> <string name="description_target_soundon" msgid="30052466675500172">"Audio attivato"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Ricerca"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Fai scorrere per sbloccare."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Collega gli auricolari per ascoltare la pronuncia dei tasti premuti per la password."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto."</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index c8d1d6b..613410f 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"מאפשר ליישום לשנות את הסיבוב של המסך בכל עת. הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"שינוי מהירות המצביע"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"מאפשר ליישום לשנות את המהירות של מצביע העכבר או לוח המגע בכל עת. יישומים רגילים לא אמורים לעולם להזדקק להרשאה זו."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"שליחת אותות Linux ליישומים"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"מאפשר ליישום לבקש שהאות שנקלט יישלח לכל התהליכים המתמשכים."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"הגדרת היישום לפעול תמיד"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"הגדרת שעה"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"הגדר תאריך"</string> <string name="date_time_set" msgid="5777075614321087758">"הגדר"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"בוצע"</string> <string name="default_permission_group" msgid="2690160991405646128">"ברירת מחדל"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"חדש: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"לא דרושים אישורים"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"גע כדי להשבית את ניקוי הבאגים בהתקן ה-USB."</string> <string name="select_input_method" msgid="4653387336791222978">"בחר שיטת הזנה"</string> <string name="configure_input_methods" msgid="9091652157722495116">"הגדר שיטות קלט"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"מועמדים"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"הוסף חשבון"</string> <string name="choose_account_text" msgid="6303348737197849675">"באיזה חשבון ברצונך להשתמש?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"הוסף חשבון"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"הוסף"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"הפחת"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> גע והחזק."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"הסט למעלה כדי להוסיף ולמטה כדי להפחית."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"הוסף דקה"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"הפחת דקה"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"הוסף שעה"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"הפחת שעה"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"הגדר PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"הגדר AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"הוסף חודש"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"הפחת חודש"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"הוסף יום"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"הפחת יום"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"הוסף שנה"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"הפחת שנה"</string> <string name="checkbox_checked" msgid="7222044992652711167">"מסומן"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"לא מסומן"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"נבחר"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"שתף עם"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"שתף עם <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"ידית להחלקה. גע והחזק."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"הסט למעלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"הסט למטה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"הסט שמאלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"הסט ימינה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"בטל נעילה"</string> <string name="description_target_camera" msgid="969071997552486814">"מצלמה"</string> <string name="description_target_silent" msgid="893551287746522182">"שקט"</string> <string name="description_target_soundon" msgid="30052466675500172">"הקול פועל"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"חיפוש"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"החלק לביטול נעילה."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"חבר אוזניות כדי לשמוע הקראה של מפתחות סיסמה."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"נקודה."</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 5d3e1c6..5e5010d 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"いつでも画面の向きを変更することをアプリに許可します。通常のアプリでは不要です。"</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ポインタの速度の変更"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"マウスまたはトラックパッドのポインタの速度をいつでも変更することをアプリに許可します。通常のアプリでは不要です。"</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"アプリへのLinuxシグナルの送信"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"受信したシグナルをすべての継続プロセスに送信するようリクエストすることをアプリに許可します。"</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"アプリの常時実行"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"時刻設定"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"日付設定"</string> <string name="date_time_set" msgid="5777075614321087758">"設定"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"完了"</string> <string name="default_permission_group" msgid="2690160991405646128">"端末既定"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NEW: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"権限の許可は必要ありません"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"タップしてUSBデバッグを無効にします。"</string> <string name="select_input_method" msgid="4653387336791222978">"入力方法の選択"</string> <string name="configure_input_methods" msgid="9091652157722495116">"入力方法をセットアップ"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"候補"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"アカウントを追加"</string> <string name="choose_account_text" msgid="6303348737197849675">"どのアカウントを使用しますか?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"アカウントを追加"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"進めます"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"戻します"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g>回タップして押し続けます。"</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"上にスライドで進み、下にスライドで戻ります。"</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"1分進めます"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"1分戻します"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"1時間進めます"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"1時間戻します"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"午後に設定"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"午前に設定"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"1か月進めます"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"1か月戻します"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"1日進めます"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"1日戻します"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"1年進めます"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"1年戻します"</string> <string name="checkbox_checked" msgid="7222044992652711167">"ON"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"OFF"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"ON"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"共有"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>と共有"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"スライダーハンドルです。押し続けます。"</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"上にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string> + <string name="description_direction_down" msgid="5087739728639014595">"下にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string> + <string name="description_direction_left" msgid="7207478719805562165">"左にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string> + <string name="description_direction_right" msgid="8034433242579600980">"右にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string> <string name="description_target_unlock" msgid="2228524900439801453">"ロックを解除"</string> <string name="description_target_camera" msgid="969071997552486814">"カメラ"</string> <string name="description_target_silent" msgid="893551287746522182">"マナーモード"</string> <string name="description_target_soundon" msgid="30052466675500172">"サウンドON"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"検索します"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ロック解除するにはスワイプします。"</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"パスワードのキーが音声出力されるのでヘッドセットを接続してください。"</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ドット。"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 6be9465..5556aae 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"앱이 언제든지 화면 회전을 변경할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"포인터 속도 변경"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"앱이 언제든지 마우스 또는 트랙패드 포인터의 속도를 변경할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"앱에 Linux 시그널 보내기"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"제공된 시그널을 모든 영구 프로세스로 전송하는 것을 앱이 요청할 수 있도록 허용합니다."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"앱이 항상 실행되도록 설정"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"시간 설정"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"날짜 설정"</string> <string name="date_time_set" msgid="5777075614321087758">"설정"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"완료"</string> <string name="default_permission_group" msgid="2690160991405646128">"기본값"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"신규: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"권한 필요 없음"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB 디버깅을 사용하지 않으려면 터치하세요."</string> <string name="select_input_method" msgid="4653387336791222978">"입력 방법 선택"</string> <string name="configure_input_methods" msgid="9091652157722495116">"입력 방법 설정"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"가능한 원인"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"계정 추가"</string> <string name="choose_account_text" msgid="6303348737197849675">"사용할 계정을 선택하세요."</string> <string name="add_account_button_label" msgid="3611982894853435874">"계정 추가"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"늘리기"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"줄이기"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> 길게 터치하세요."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"늘리려면 위로 슬라이드하고 줄이려면 아래로 슬라이드합니다."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"\'분\'을 늘립니다."</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"\'분\'을 줄입니다."</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"\'시간\'을 늘립니다."</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"\'시간\'을 줄입니다."</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM 설정"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM 설정"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"\'월\'을 늘립니다."</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"\'월\'을 줄입니다."</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"\'일\'을 늘립니다."</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"\'일\'을 줄입니다."</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"\'연도\'를 늘립니다."</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"\'연도\'를 줄입니다."</string> <string name="checkbox_checked" msgid="7222044992652711167">"확인"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"선택 안함"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"선택됨"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"공유 대상:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>와(과) 공유"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"슬라이딩 핸들을 길게 터치하세요."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string> + <string name="description_direction_down" msgid="5087739728639014595">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 아래로 슬라이드"</string> + <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 왼쪽으로 슬라이드"</string> + <string name="description_direction_right" msgid="8034433242579600980">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 오른쪽으로 슬라이드"</string> <string name="description_target_unlock" msgid="2228524900439801453">"잠금 해제"</string> <string name="description_target_camera" msgid="969071997552486814">"카메라"</string> <string name="description_target_silent" msgid="893551287746522182">"무음"</string> <string name="description_target_soundon" msgid="30052466675500172">"사운드 켜기"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"검색"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"스와이프하여 잠급니다."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"비밀번호 키를 음성으로 들으려면 헤드셋을 연결하세요."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"점"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index da81e3e..9e82e8c 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Leidžiama programai bet kada kaitalioti ekraną. Įprastoms programoms to neturėtų prireikti."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"keisti žymiklio greitį"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Leidžiama programai keisti pelės ar sensorinio pulto žymiklio greitį. Įprastoms programoms to neturėtų prireikti."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"siųsti „Linux“ signalus programoms"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Leidžiama programai pateikti užklausą, kad teikiamas signalas būtų siunčiamas visiems nuolatiniams procesams."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"nustatyti, kad programa būtų visada vykdoma"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nustatyti laiką"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nustatyti datą"</string> <string name="date_time_set" msgid="5777075614321087758">"Nustatyti"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Baigta"</string> <string name="default_permission_group" msgid="2690160991405646128">"Numatytasis"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NAUJAS: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nereikia leidimų"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Palieskite, kad neleistumėte USB derinimo."</string> <string name="select_input_method" msgid="4653387336791222978">"Pasirinkite įvesties metodą"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Nustatyti įvesties metodus"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidatai"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Pridėti paskyrą"</string> <string name="choose_account_text" msgid="6303348737197849675">"Kurią paskyrą norite naudoti?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Pridėti paskyrą"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Padidinti"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Sumažinti"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Palieskite <xliff:g id="VALUE">%s</xliff:g> ir laikykite."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Slinkite aukštyn, kad padidintumėte, ir žemyn, kad sumažintumėte."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Padidinti minučių skaičių"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Sumažinti minučių skaičių"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Padidinti valandų skaičių"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Sumažinti valandų skaičių"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nustatyti po pusiaudienio"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nustatyti prieš pusiaudienį"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Padidinti mėnesių skaičių"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Sumažinti mėnesių skaičių"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Padidinti dienų skaičių"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Sumažinti dienų skaičių"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Padidinti metų skaičių"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Sumažinti metų skaičių"</string> <string name="checkbox_checked" msgid="7222044992652711167">"pažymėtas"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nepatikrinta"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"pasirinkta"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Bendrinti su"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Bendrinti su „<xliff:g id="APPLICATION_NAME">%s</xliff:g>“"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Slydimo valdymas. Palieskite ir laikykite."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Slyskite aukštyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Slyskite žemyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Slyskite į kairę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Slyskite į dešinę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Atrakinti"</string> <string name="description_target_camera" msgid="969071997552486814">"Vaizdo kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Begarsis"</string> <string name="description_target_soundon" msgid="30052466675500172">"Garsas įjungtas"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Paieška"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Perbraukite pirštu, kad atrakintumėte."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Prijunkite ausines, kad išgirstumėte sakomus slaptažodžio klavišus."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Taškas."</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 5489714..ae451e0 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Ļauj lietotnei jebkurā laikā mainīt ekrāna pozīciju. Parastajām lietotnēm tas nekad nav nepieciešams."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Rādītāja ātruma mainīšana"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Ļauj lietotnei jebkurā laikā mainīt peles vai skārienpaliktņa rādītāja ātrumu. Parastajām lietotnēm tas nekad nav nepieciešams."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"sūtīt Linux signālus lietotnēm"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Ļauj lietotnei pieprasīt, lai piegādātais signāls tiktu sūtīts visiem pastāvīgajiem procesiem."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"likt lietotnei vienmēr darboties"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Laika iestatīšana"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datuma iestatīšana"</string> <string name="date_time_set" msgid="5777075614321087758">"Iestatīt"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Gatavs"</string> <string name="default_permission_group" msgid="2690160991405646128">"Noklusējums"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"JAUNA: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Atļaujas nav nepieciešamas."</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Pieskarieties, lai atspējotu USB atkļūdošanu."</string> <string name="select_input_method" msgid="4653387336791222978">"Ievades metodes izvēle"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Iestatīt ievades metodes"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidāti"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Pievienot kontu"</string> <string name="choose_account_text" msgid="6303348737197849675">"Kuru kontu vēlaties izmantot?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Pievienot kontu"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Palielināt"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Samazināt"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g>: pieskarieties un turiet nospiestu."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Velciet uz augšu, lai palielinātu vērtību, un uz leju, lai to samazinātu."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Norādīt vēlākas minūtes"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Norādīt agrākas minūtes"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Norādīt vēlāku stundu"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Norādīt agrāku stundu"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Iestatīt pēcpusdienas laiku"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Iestatīt priekšpusdienas laiku"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Norādīt vēlāku mēnesi"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Norādīt agrāku mēnesi"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Norādīt vēlāku dienu"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Norādīt agrāku dienu"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Norādīt vēlāku gadu"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Norādīt agrāku gadu"</string> <string name="checkbox_checked" msgid="7222044992652711167">"atzīmēta"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nav atzīmēta"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"atlasīta"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Kopīgot ar:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Kopīgot ar lietojumprogrammu <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Bīdāms turis. Pieskarieties tam un turiet to nospiestu."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Velciet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Velciet uz leju, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Velciet pa kreisi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Velciet pa labi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Atbloķēt"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Klusums"</string> <string name="description_target_soundon" msgid="30052466675500172">"Skaņa ieslēgta"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Meklēt"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Velciet ar pirkstu, lai atbloķētu."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pievienojiet austiņas, lai dzirdētu paroles taustiņu nosaukumus."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkts."</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index da9ca41..ead175b 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Membenarkan apl untuk menukar putaran skrin pada bila-bila masa. Tidak sekali-kali diperlukan untuk apl biasa."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"tukar kelajuan penuding"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Membenarkan apl untuk menukar kelajuan penunjuk tetikus atau pad jejak pada bila-bila masa. Tidak sekali-kali diperlukan untuk apl biasa."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"hantar isyarat Linux kepada apl"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Membenarkan apl meminta isyarat yang dibekalkan dihantar kepada semua proses yang berterusan."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"buatkan apl sentiasa berjalan"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Tetapkan masa"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tetapkan tarikh"</string> <string name="date_time_set" msgid="5777075614321087758">"Tetapkan"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Selesai"</string> <string name="default_permission_group" msgid="2690160991405646128">"Lalai"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"BAHARU: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Tiada kebenaran diperlukan"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Sentuh untuk melumpuhkan penyahpepijatan USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Pilih kaedah input"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Sediakan kaedah input"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"calon"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Tambah akaun"</string> <string name="choose_account_text" msgid="6303348737197849675">"Akaun mana yang mahu anda gunakan?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Tambah akaun"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Tingkatkan"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Kurangkan"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> sentuh terus."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Luncurkan ke atas untuk meningkatkan dan ke bawah untuk mengurangkan."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Tingkatkan minit"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Kurangkan minit"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Tingkatkan jam"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Kurangkan jam"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Tetapkan PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Tetapkan AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Tingkatkan bulan"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Kurangkan bulan"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Tingkatkan hari"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Kurangkan hari"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Tingkatkan tahun"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Kurangkan tahun"</string> <string name="checkbox_checked" msgid="7222044992652711167">"ditandakan"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"tidak ditandakan"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"dipilih"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Kongsi dengan"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Kongsi dengan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Pemegang gelongsor. Sentuh & tahan."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Luncurkan ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Luncurkan ke bawah untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Luncurkan ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Luncurkan ke kanan untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Buka kunci"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Senyap"</string> <string name="description_target_soundon" msgid="30052466675500172">"Bunyi dihidupkan"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Carian"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Leret untuk membuka kunci."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pasangkan set kepala untuk mendengar kekunci kata laluan disebutkan."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Titik."</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 28fc1a8..bbd846f 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Gir appen tillatelse til når som helst å endre rotasjonen av skjermen. Skal aldri være nødvendig for vanlige apper."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"endre pekerhastighet"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Lar appen når som helst endre markørhastigheten til musen eller styreflaten. Skal aldri være nødvendig for vanlige apper."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"sende Linux-signaler til apper"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Lar appen be om at det leverte signalet sendes til alle vedvarende prosesser."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"angi at appen alltid skal kjøre"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Stille klokken"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angi dato"</string> <string name="date_time_set" msgid="5777075614321087758">"Lagre"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Ferdig"</string> <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NYTT: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Trenger ingen rettigheter"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Trykk for å deaktivere USB-feilsøking."</string> <string name="select_input_method" msgid="4653387336791222978">"Velg inndatametode"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Konfigurer inndatametoder"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string> <string name="candidates_style" msgid="4333913089637062257">"TAG_FONT"<u>"kandidater"</u>"CLOSE_FONT"</string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Legg til en konto"</string> <string name="choose_account_text" msgid="6303348737197849675">"Hvilken konto vil du bruke?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Legg til konto"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Øk"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Reduser"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> – trykk og hold inne."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Dra opp for å øke og ned for å redusere."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Øk minutter"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Reduser minutter"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Øk timer"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Reduser timer"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Angi p.m."</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Angi a.m."</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Øk måneder"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Reduser måneder"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Øk dager"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reduser dager"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Øk år"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reduser år"</string> <string name="checkbox_checked" msgid="7222044992652711167">"valgt"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"ikke valgt"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"valgt"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Del med"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Del med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Glidebryter. Trykk og hold inne."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Dra opp for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Dra ned for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Dra til venstre for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Dra til høyre for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Lås opp"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Stille"</string> <string name="description_target_soundon" msgid="30052466675500172">"Lyd på"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Søk"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Sveip for å låse opp."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Koble til hodetelefoner for å høre opplesing av bokstavene i passordet."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punktum."</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 51e62e8..8440d62 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Hiermee kan de app de rotatie van het scherm op elk moment wijzigen. Nooit vereist voor normale apps."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"aanwijzersnelheid wijzigen"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Hiermee kan de app de snelheid van de muis- of trackpadaanwijzer op elk moment wijzigen. Nooit vereist voor normale apps."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Linux-signalen verzenden naar apps"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Hiermee kan de app ervoor zorgen dat het geleverde signaal wordt verzonden naar alle persistente processen."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"app altijd laten uitvoeren"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Tijd instellen"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum instellen"</string> <string name="date_time_set" msgid="5777075614321087758">"Instellen"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Gereed"</string> <string name="default_permission_group" msgid="2690160991405646128">"Standaard"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NIEUW: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Geen machtigingen vereist"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Raak deze optie aan om USB-foutopsporing uit te schakelen."</string> <string name="select_input_method" msgid="4653387336791222978">"Invoermethode selecteren"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Invoermethoden instellen"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidaten"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Een account toevoegen"</string> <string name="choose_account_text" msgid="6303348737197849675">"Welk account wilt u gebruiken?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Account toevoegen"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Verhogen"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Verlagen"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> blijven aanraken."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Veeg omhoog om te verhogen en omlaag om te verlagen."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Hogere waarde voor minuten"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Lagere waarde voor minuten"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Hogere waarde voor uren"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Lagere waarde voor uren"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM instellen"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM instellen"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Hogere waarde voor maand"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Lagere waarde voor maand"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Hogere waarde voor dag"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Lagere waarde voor dag"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Hogere waarde voor jaar"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Lagere waarde voor jaar"</string> <string name="checkbox_checked" msgid="7222044992652711167">"aangevinkt"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"niet aangevinkt"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"geselecteerd"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Delen met"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Delen met <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Schuifgreep. Tikken en blijven aanraken."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Veeg omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Veeg omlaag voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Veeg naar links voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Veeg naar rechts voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Ontgrendelen"</string> <string name="description_target_camera" msgid="969071997552486814">"Camera"</string> <string name="description_target_silent" msgid="893551287746522182">"Stil"</string> <string name="description_target_soundon" msgid="30052466675500172">"Geluid aan"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Zoeken"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Vegen om te ontgrendelen"</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Sluit een headset aan om wachtwoordtoetsen te laten voorlezen."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Stip."</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index ee10502..ee1e6a3 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Pozwala aplikacji na zmianę obrotu ekranu w dowolnym momencie. To uprawnienie nie powinno być potrzebne zwykłym aplikacjom."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"zmiana szybkości wskaźnika"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Pozwala aplikacji zmienić szybkość wskaźnika myszy lub touchpada w dowolnym momencie. Nieprzeznaczone dla zwykłych aplikacji."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"wysyłanie sygnałów systemu Linux do aplikacji"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Pozwala aplikacji na żądanie, aby dostarczony sygnał został wysłany do wszystkich trwałych procesów."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"sprawianie, że aplikacja jest cały czas uruchomiona"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ustaw godzinę"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ustaw datę"</string> <string name="date_time_set" msgid="5777075614321087758">"Ustaw"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Gotowe"</string> <string name="default_permission_group" msgid="2690160991405646128">"Domyślne"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOWE: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nie są wymagane żadne uprawnienia"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknij, aby wyłączyć debugowanie USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Wybierz metodę wprowadzania"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Konfiguruj metody wprowadzania"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandydaci"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Dodaj konto"</string> <string name="choose_account_text" msgid="6303348737197849675">"Którego konta chcesz użyć?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj konto"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Zwiększ"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Zmniejsz"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> dotknij i przytrzymaj."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Przesuń w górę, by zwiększyć, i w dół, by zmniejszyć."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Zmień minutę na późniejszą"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Zmień minutę na wcześniejszą"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Zmień godzinę na późniejszą"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Zmień godzinę na wcześniejszą"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Ustaw PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Ustaw AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Zmień miesiąc na późniejszy"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Zmień miesiąc na wcześniejszy"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Zmień dzień na późniejszy"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Zmień dzień na wcześniejszy"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Zmień rok na późniejszy"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Zmień rok na wcześniejszy"</string> <string name="checkbox_checked" msgid="7222044992652711167">"zaznaczono"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nie zaznaczono"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"wybrano"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Udostępnij przez"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Udostępnij przez <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Uchwyt przesuwny. Dotknij i przytrzymaj."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Przesuń w górę: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Przesuń w dół: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Przesuń w lewo: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Przesuń w prawo: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Odblokuj"</string> <string name="description_target_camera" msgid="969071997552486814">"Aparat"</string> <string name="description_target_silent" msgid="893551287746522182">"Wyciszenie"</string> <string name="description_target_soundon" msgid="30052466675500172">"Włącz dźwięk"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Szukaj"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Przesuń, aby odblokować."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Podłącz zestaw słuchawkowy, aby wysłuchać znaków hasła wypowiadanych na głos."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Kropka"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 290ae19..393ba17 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite que a aplicação altere a rotação do ecrã em qualquer momento. Nunca deve ser necessário para aplicações normais."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"alterar a veloc. do ponteiro"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite à aplicação mudar em qualquer altura a velocidade do ponteiro do rato ou do trackpad. Nunca deverá ser necessário para aplicações normais."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"enviar sinais Linux para aplicações"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite à aplicação pedir que o sinal fornecido seja enviado a todos os processos persistentes."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"fazer com que a aplicação seja sempre executada"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string> <string name="date_time_set" msgid="5777075614321087758">"Definir"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Concluído"</string> <string name="default_permission_group" msgid="2690160991405646128">"Predefinido"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVA: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Não são necessárias permissões"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Escolher o método de entrada"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Configurar métodos de introdução"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Adicionar uma conta"</string> <string name="choose_account_text" msgid="6303348737197849675">"Que conta pretende utilizar?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Adicionar conta"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Aumentar"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Diminuir"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Toque sem soltar em <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Deslizar para cima para aumentar e para baixo para diminuir."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Aumentar minutos"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Diminuir minutos"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Aumentar horas"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Diminuir hora"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Definir PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Definir AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Aumentar mês"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Diminuir mês"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Aumentar o dia"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Diminuir dia"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar ano"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Diminuir ano"</string> <string name="checkbox_checked" msgid="7222044992652711167">"marcado"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"desmarcado"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"selecionado"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Partilhar com:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartilhar com <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Barra deslizante. Toque & não solte."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Deslize para cima para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Deslize para baixo para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Deslize para a esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Deslize para a direita para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Desbloquear"</string> <string name="description_target_camera" msgid="969071997552486814">"Câmara"</string> <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string> <string name="description_target_soundon" msgid="30052466675500172">"Som ativado"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Deslizar rapidamente para desbloquear."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Ligue os auscultadores com microfone integrado para ouvir as teclas da palavra-passe."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Ponto."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 09fe685..bb145f7 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite que o aplicativo gire a tela a qualquer momento. Nunca deve ser necessário para aplicativos normais."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"alterar velocidade do ponteiro"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite que o aplicativo altere a velocidade do cursos do mouse ou trackpad a qualquer momento. Nunca deve ser necessário para aplicativos normais."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"enviar sinais para aplicativos Linux"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite que o aplicativo solicite o envio do sinal fornecido a todos os processos persistentes."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"sempre executar o aplicativo"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string> <string name="date_time_set" msgid="5777075614321087758">"Definir"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Concluído"</string> <string name="default_permission_group" msgid="2690160991405646128">"Padrão"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVO: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nenhuma permissão necessária"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Toque para desativar a depuração do USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Selecione o método de entrada"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Configurar métodos de entrada"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidatos"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Adicionar uma conta"</string> <string name="choose_account_text" msgid="6303348737197849675">"Qual conta você deseja usar?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Adicionar conta"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Aumentar"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Diminuir"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> toque e mantenha pressionado."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Deslize para cima para aumentar e para baixo para diminuir."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Aumentar minuto"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Diminuir minuto"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Aumentar hora"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Diminuir hora"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Configurar valor PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Configurar valor AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Aumentar mês"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Diminuir mês"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Aumentar dia"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Diminuir dia"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar ano"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Diminuir ano"</string> <string name="checkbox_checked" msgid="7222044992652711167">"verificado"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"não selecionado"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"selecionado"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Compartilhar com"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartilhar com <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Recurso deslizante. Toque e segure."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para cima."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para baixo."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para a esquerda."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para a direita."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Desbloquear"</string> <string name="description_target_camera" msgid="969071997552486814">"Câmera"</string> <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string> <string name="description_target_soundon" msgid="30052466675500172">"Som ativado"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Deslize para desbloquear."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecte um fone de ouvido para ouvir as teclas da senha."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Ponto final."</string> diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml index f4bc105..8b0718f 100644 --- a/core/res/res/values-rm/strings.xml +++ b/core/res/res/values-rm/strings.xml @@ -399,6 +399,10 @@ <skip /> <!-- no translation found for permdesc_setPointerSpeed (6866563234274104233) --> <skip /> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <!-- no translation found for permlab_signalPersistentProcesses (4539002991947376659) --> <skip /> <!-- no translation found for permdesc_signalPersistentProcesses (4896992079182649141) --> @@ -1575,6 +1579,10 @@ <skip /> <!-- no translation found for configure_input_methods (9091652157722495116) --> <skip /> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidats"</u></string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 9dee72d..d93d8d1 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Permite aplicaţiei să modifice rotaţia ecranului în orice moment. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"modifică viteza indicatorului"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Permite aplicaţiei să modifice oricând viteza indicatorului mouse-ului sau al trackpadului. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"trimitere semnale Linux către aplicaţii"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Permite aplicaţiei să solicite trimiterea semnalului furnizat către toate procesele persistente."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"rulare continuă a aplicaţiei"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Setaţi ora"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setaţi data"</string> <string name="date_time_set" msgid="5777075614321087758">"Setaţi"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Terminat"</string> <string name="default_permission_group" msgid="2690160991405646128">"Prestabilit"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOU: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nu se solicită nicio permisiune"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Atingeţi pentru a dezactiva depanarea USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Alegeţi metoda de introducere"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Configurare metode introducere"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"candidaţi"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Adăugaţi un cont"</string> <string name="choose_account_text" msgid="6303348737197849675">"Ce cont doriţi să utilizaţi?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Adăugaţi un cont"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Creşteţi"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Reduceţi"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Atingeţi şi ţineţi apăsat <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Glisaţi în sus pentru a creşte şi în jos pentru a reduce."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Creşteţi valoarea pentru minute"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Reduceţi valoarea pentru minute"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Creşteţi valoarea pentru oră"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Reduceţi valoarea pentru oră"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Setaţi valoarea PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Setaţi valoarea AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Creşteţi valoarea pentru lună"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Reduceţi valoarea pentru lună"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Creşteţi valoarea pentru zi"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reduceţi valoarea pentru zi"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Creşteţi valoarea pentru an"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reduceţi valoarea pentru an"</string> <string name="checkbox_checked" msgid="7222044992652711167">"bifată"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nebifată"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"selectat"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Permiteţi accesul pentru"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Permiteţi accesul pentru <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Mâner glisant. Atingeţi şi ţineţi apăsat."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Glisaţi în jos pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Glisaţi spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Glisaţi spre dreapta pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Deblocaţi"</string> <string name="description_target_camera" msgid="969071997552486814">"Cameră foto"</string> <string name="description_target_silent" msgid="893551287746522182">"Silenţios"</string> <string name="description_target_soundon" msgid="30052466675500172">"Sunet activat"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Căutaţi"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glisaţi pentru a debloca."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conectaţi un set căşti-microfon pentru a auzi tastele apăsate când introduceţi parola."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punct."</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 97391bf..2743763 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Приложение сможет менять ориентацию экрана. Это разрешение не используется обычными приложениями."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"изменять скорость указателя"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Приложение сможет в любой момент изменить скорость движения указателя мыши или сенсорной панели. Это разрешение не используется обычными приложениями."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"отправка сигналов Linux приложениям"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Приложение сможет запрашивать передачу полученного сигнала всем постоянным процессам."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"постоянная работа приложения"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Настройка времени"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Настройка даты"</string> <string name="date_time_set" msgid="5777075614321087758">"Установить"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Готово"</string> <string name="default_permission_group" msgid="2690160991405646128">"По умолчанию"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВОЕ: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Не требуется разрешений"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Нажмите, чтобы отключить отладку по USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Выберите способ ввода"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Настройка способов ввода"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"варианты"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Добавить аккаунт"</string> <string name="choose_account_text" msgid="6303348737197849675">"Выберите аккаунт"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Добавить аккаунт"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Увеличить"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Уменьшить"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Нажмите и удерживайте <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Проведите вверх, чтобы увеличить значение, и вниз, чтобы уменьшить его."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"На минуту вперед"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"На минуту назад"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"На час вперед"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"На час назад"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Установить время после полудня"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Установить время до полудня"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"На месяц вперед"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"На месяц назад"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"На день вперед"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"На день назад"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"На год вперед"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"На год назад"</string> <string name="checkbox_checked" msgid="7222044992652711167">"установлено"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"не установлено"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"выбрано"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Открыть доступ:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Открыть доступ приложению \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\""</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Перетаскиваемый значок блокировки. Нажмите и удерживайте."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Проведите вниз, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Проведите влево, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Проведите вправо, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Разблокировать"</string> <string name="description_target_camera" msgid="969071997552486814">"Камера"</string> <string name="description_target_silent" msgid="893551287746522182">"Без звука"</string> <string name="description_target_soundon" msgid="30052466675500172">"Включить звук"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Поиск"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Проведите по экрану, чтобы разблокировать устройство."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Подключите гарнитуру, чтобы услышать пароль."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Точка"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index c7c7b4f..49d04c3 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Umožňuje aplikácii kedykoľvek zmeniť otáčanie obrazovky. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"zmena rýchlosti ukazovateľa"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Umožňuje aplikácii kedykoľvek zmeniť rýchlosť kurzora myši alebo touchpadu. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"odoslať aplikáciám signály systému Linux"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Umožňuje aplikácii vyžiadať odoslanie poskytnutého signálu všetkým trvalým procesom."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"nastaviť, aby bola aplikácia neustále spustená"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastaviť čas"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastaviť dátum"</string> <string name="date_time_set" msgid="5777075614321087758">"Nastaviť"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Hotovo"</string> <string name="default_permission_group" msgid="2690160991405646128">"Predvolené"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVINKA: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Nevyžadujú sa žiadne oprávnenia."</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotknutím zakážete ladenie USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Zvoliť metódu vstupu"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Nastavenie metód vstupu"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidáti"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Pridať účet"</string> <string name="choose_account_text" msgid="6303348737197849675">"Ktorý účet chcete použiť?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Pridať účet"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Zvýšiť"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Znížiť"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Dotknite sa a podržte <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Ak chcete hodnotu zvýšiť, prejdite prstom nahor. Ak chcete hodnotu znížiť, prejdite prstom nadol."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Pridať minútu"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Ubrať minútu"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Pridať hodinu"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Ubrať hodinu"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nastaviť čas popoludní"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nastaviť čas dopoludnia"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Pridať mesiac"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Ubrať mesiac"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Pridať deň"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Ubrať deň"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Pridať rok"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Ubrať rok"</string> <string name="checkbox_checked" msgid="7222044992652711167">"začiarknuté"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"nezačiarknuté"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"vybratý"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Zdieľať s"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Zdieľať s aplikáciou <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Posuvné tlačidlo. Dotknite sa a podržte."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Prejdite prstom nahor: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Prejdite prstom nadol: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Prejdite prstom doľava: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Prejdite prstom doprava: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Odomknúť"</string> <string name="description_target_camera" msgid="969071997552486814">"Fotoaparát"</string> <string name="description_target_silent" msgid="893551287746522182">"Tichý"</string> <string name="description_target_soundon" msgid="30052466675500172">"Zapnúť zvuk"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Vyhľadávanie"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Posunom odomknúť."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Ak si chcete vypočuť vyslovené klávesy hesla, pripojte náhlavnú súpravu."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Bodka."</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 4dc425b..55f3593 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Programu omogoča, da kadar koli zasuka zaslon. Ne uporabljajte za navadne programe."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"spreminjanje hitrosti kazalca"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Programu omogoča spreminjanje hitrosti kazalca miške ali sledilne ploščice. Tega ni treba nikoli uporabiti za navadne programe."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"pošiljanje signalov Linuxa programom"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Programu omogoča, da zahteva, da je posredovani signal poslan vsem trajnim procesom."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"neprekinjeno izvajanje programov"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastavi uro"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavi datum"</string> <string name="date_time_set" msgid="5777075614321087758">"Nastavi"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Končano"</string> <string name="default_permission_group" msgid="2690160991405646128">"Privzeto"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVO: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Ni zahtevanih dovoljenj"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Dotaknite se, če želite onemogočiti iskanje in odpravljanje napak prek vrat USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Izberite način vnosa"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Nastavi načine vnosa"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidati"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Dodajanje računa"</string> <string name="choose_account_text" msgid="6303348737197849675">"Kateri račun želite uporabiti?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj račun"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Več"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Manj"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Dotaknite se vrednosti <xliff:g id="VALUE">%s</xliff:g> in jo pridržite."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Povlecite navzgor za povečanje in navzdol za zmanjšanje."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Povečanje vrednosti za minuto"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Zmanjšanje vrednosti za minuto"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Povečanje vrednosti za uro"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Zmanjšanje vrednosti za uro"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nastavi PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nastavi AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Povečanje vrednosti za mesec"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Zmanjšanje vrednosti za mesec"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Povečanje vrednosti za dan"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Zmanjšanje vrednosti za dan"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Povečanje vrednosti za leto"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Zmanjšanje vrednosti za leto"</string> <string name="checkbox_checked" msgid="7222044992652711167">"potrjeno"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"ni odkljukano"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"izbrano"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Delite z"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Delite s programom <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Drsna ročica. Dotaknite se in pridržite."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Povlecite navzgor za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Povlecite navzdol za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Povlecite v levo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Povlecite v desno za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Odkleni"</string> <string name="description_target_camera" msgid="969071997552486814">"Fotoaparat"</string> <string name="description_target_silent" msgid="893551287746522182">"Tiho"</string> <string name="description_target_soundon" msgid="30052466675500172">"Vklopljen zvok"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Iskanje"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Povlecite, če želite odkleniti."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Priključite slušalke, če želite slišati izgovorjene tipke gesla."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Pika."</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index da7a0f2..de03bec 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Дозвољава апликацији да у сваком тренутку промени ротацију екрана. Уобичајене апликације никада не би требало да је користе."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"промена брзине показивача"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Дозвољава апликацији да у било ком тренутку промени брзину показивача миша или показивачког уређаја са плочицом. Уобичајене апликације никада не би требало да је користе."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"слање Linux сигнала апликацијама"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Дозвољава апликацији да захтева да испоручени сигнал буде послат свим трајним процесима."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"омогућавање непрекидне активности апликације"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Подешавање времена"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Подешавање датума"</string> <string name="date_time_set" msgid="5777075614321087758">"Подеси"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Готово"</string> <string name="default_permission_group" msgid="2690160991405646128">"Подразумевано"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВО: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Није потребна ниједна дозвола"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Додирните да бисте онемогућили отклањање грешака са USB-а."</string> <string name="select_input_method" msgid="4653387336791222978">"Избор метода уноса"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Подеси методе уноса"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Додај налог"</string> <string name="choose_account_text" msgid="6303348737197849675">"Који налог желите да користите?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Додај налог"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Повећавање"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Смањивање"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> додирните и задржите."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Превуците нагоре да бисте повећали, а надоле да бисте смањили."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Повећавање минута"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Смањивање минута"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Повећавање сати"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Смањивање сати"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Подеси по подне"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Подеси пре подне"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Повећавање месеца"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Смањивање месеца"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Повећавање дана"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Смањивање дана"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Повећавање године"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Смањивање године"</string> <string name="checkbox_checked" msgid="7222044992652711167">"изабрано"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"није потврђено"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"изабрано"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Дели са"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Дели са апликацијом <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Клизна ручица. Додирните и задржите."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Превуците нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Превуците надоле за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Превуците улево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Превуците удесно за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Откључај"</string> <string name="description_target_camera" msgid="969071997552486814">"Камера"</string> <string name="description_target_silent" msgid="893551287746522182">"Нечујно"</string> <string name="description_target_soundon" msgid="30052466675500172">"Укључи звук"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Претрага"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Превуците да бисте откључали."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Прикључите слушалице да бисте чули изговорене тастере за лозинку."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Тачка."</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 1c916f9..7448ff8 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Gör att appen när som helst kan ändra skärmläget. Behövs inte för vanliga appar."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"ändra markörens hastighet"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Tillåter att appen när som helst ändrar hastigheten för musens eller styrplattans markör. Ska inte behövas för vanliga appar."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"skicka Linux-signaler till appar"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Tillåter att appen begär att den angivna signalen skickas till alla beständiga processer."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"se till att appen alltid körs"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ange tid"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ange datum"</string> <string name="date_time_set" msgid="5777075614321087758">"Ställ in"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Klar"</string> <string name="default_permission_group" msgid="2690160991405646128">"Standardinställning"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NY: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Inga behörigheter krävs"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Tryck om du vill inaktivera USB-felsökning."</string> <string name="select_input_method" msgid="4653387336791222978">"Välj inmatningsmetod"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Konfigurera inmatningsmetoder"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"kandidater"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Lägg till ett konto"</string> <string name="choose_account_text" msgid="6303348737197849675">"Vilket konto vill du använda?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Lägg till konto"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Öka"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Minska"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> tryck länge."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Dra uppåt för att öka och nedåt för att minska."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Öka minuter"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Minska minuter"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Öka timmar"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Minska timmar"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Ange em"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Ange fm"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Öka månader"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Minska månader"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Öka dagar"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Minska dagar"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Öka år"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Minska år"</string> <string name="checkbox_checked" msgid="7222044992652711167">"markerat"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"inte markerat"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"markerade"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Dela med"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Dela med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Skärmlåsfunktion. Tryck och dra."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Dra uppåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Dra nedåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Dra åt vänster för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Dra åt höger för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Lås upp"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Tyst"</string> <string name="description_target_soundon" msgid="30052466675500172">"Ljud på"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Sök"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Lås upp genom att dra."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Anslut mikrofonlurar om du vill att lösenordet ska läsas upp."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 6b64163..ab6c82f 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Inaruhusu programu kubadilisha mzunguko wa skrini wakati wowote. Kamwe hazihitajiki kwa programu za kawaida."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Badilisha kasi ya pointa"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Inaruhusu programu kubadilisha kasi ya kielekezi cha kipanya au pedi ya kufuatilia wakati wowote. Kamwe haitahitajika kwa programu za kawaida."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Tuma ishara za Linux kwa programu"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Inaruhusu programu kuomba ishara iliyotolewa kutumwa kwa michakato inyoendelea."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"Fanya programu kuendeshwa kila mara"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Weka muda"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Weka tarehe"</string> <string name="date_time_set" msgid="5777075614321087758">"Weka"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Imekamilika"</string> <string name="default_permission_group" msgid="2690160991405646128">"Chaguo-msingi"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">" MPYA: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Hakuna vibali vinavyohitajika"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili kulemaza utatuaji wa USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Chagua njia ya ingizo"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Weka mbinu za ingizo"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"wagombeaji"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Ongeza akaunti"</string> <string name="choose_account_text" msgid="6303348737197849675">"Je, ni akaunti gani unataka kutumia?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Ongeza akaunti"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Ongeza"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Punguza"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> gusa na ushikilie."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Sogeza juu ili uongeze na chini ili upunguze."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Ongeza dakika"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Punguza dakika"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Ongeza saa"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Punguza saa"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Seti PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Seti AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Ongeza mwezi"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Punguza mwezi"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Ongeza siku"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Punguza siku"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Ongeza mwaka"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Punguza mwaka"</string> <string name="checkbox_checked" msgid="7222044992652711167">"imeangaliwa"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"haijakaguliwa"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"Iliyochaguliwa"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Gawa na"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Gawa na <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Utambo unaosonga. Gusa & shika"</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Sogeza juu kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Sogeza chini kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Sogeza kushoto kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Sogeza kulika kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Fungua"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Kimya"</string> <string name="description_target_soundon" msgid="30052466675500172">"Sauti imewashwa"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Tafuta"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Pitisha ili kufungua."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Chomeka kifaa cha sauti ili kusikiliza vibonye vya nenosiri vikizungumzwa."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Nukta."</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 88fc3b6..7007522 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"อนุญาตให้แอปพลิเคชันเปลี่ยนการหมุนของหน้าจอได้ตลอดเวลา ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"เปลี่ยนความเร็วของตัวชี้"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"อนุญาตให้แอปพลิเคชันเปลี่ยนความเร็วตัวชี้ของเมาส์หรือแทร็กแพดได้ทุกเมื่อ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"ส่งสัญญาณ Linux ไปยังแอปพลิเคชัน"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"อนุญาตให้แอปพลิเคชันร้องขอให้ส่งสัญญาณแจ้งไปยังกระบวนการที่ยังทำงานอยู่ทั้งหมด"</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"ทำให้แอปพลิเคชันทำงานเสมอ"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"ตั้งเวลา"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"ตั้งวันที่"</string> <string name="date_time_set" msgid="5777075614321087758">"ตั้งค่า"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"เสร็จสิ้น"</string> <string name="default_permission_group" msgid="2690160991405646128">"เริ่มต้น"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"ใหม่: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"ไม่ต้องการการอนุญาต"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"แตะเพื่อปิดใช้งานการแก้ไขข้อบกพร่องของ USB"</string> <string name="select_input_method" msgid="4653387336791222978">"เลือกวิธีการป้อนข้อมูล"</string> <string name="configure_input_methods" msgid="9091652157722495116">"ตั้งค่าวิธีการป้อนข้อมูล"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"ตัวเลือก"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"เพิ่มบัญชี"</string> <string name="choose_account_text" msgid="6303348737197849675">"คุณต้องการใช้บัญชีใด"</string> <string name="add_account_button_label" msgid="3611982894853435874">"เพิ่มบัญชี"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"เพิ่ม"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"ลด"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"แตะ <xliff:g id="VALUE">%s</xliff:g> ค้างไว้"</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"เลื่อนขึ้นเพื่อเพิ่มและเลื่อนลงเพื่อลด"</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"เพิ่มนาที"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"ลดนาที"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"เพิ่มชั่วโมง"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"ลดชั่วโมง"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"ตั้งค่า PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"ตั้งค่า AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"เพิ่มเดือน"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"ลดเดือน"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"เพิ่มวัน"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ลดวัน"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"เพิ่มปี"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ลดปี"</string> <string name="checkbox_checked" msgid="7222044992652711167">"เลือกไว้"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"ไม่ได้ตรวจสอบ"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"เลือกแล้ว"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"แบ่งปันกับ"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"แบ่งปันด้วย <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"ที่จับสำหรับเลื่อน แตะค้างไว้"</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string> + <string name="description_direction_down" msgid="5087739728639014595">"เลื่อนลงเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string> + <string name="description_direction_left" msgid="7207478719805562165">"เลื่อนไปทางซ้ายเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string> + <string name="description_direction_right" msgid="8034433242579600980">"เลื่อนไปทางขวาเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string> <string name="description_target_unlock" msgid="2228524900439801453">"ปลดล็อก"</string> <string name="description_target_camera" msgid="969071997552486814">"กล้องถ่ายรูป"</string> <string name="description_target_silent" msgid="893551287746522182">"ปิดเสียง"</string> <string name="description_target_soundon" msgid="30052466675500172">"เปิดเสียง"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"ค้นหา"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"กวาดเพื่อปลดล็อก"</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"เสียบชุดหูฟังเพื่อฟังเสียงเมื่อพิมพ์รหัสผ่าน"</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"เครื่องหมายจุด"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 2addf86..31ad6c8 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Pinapayagan ang app na baguhin ang pag-ikot ng screen anumang oras. Hindi kailanman dapat na kailanganin para sa normal na apps."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"baguhin ang bilis ng pointer"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Pinapayagan ang app na baguhin ang bilis ng mouse o trackpad pointer anumang oras. Hindi kailanman dapat na kailanganin para sa normal na apps."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"magpadala ng mga signal ng Linux sa apps"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Pinapayagan ang app na hilinging maipadala ang ibinigay na signal sa lahat ng nagpapatuloy na proseso."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"palaging patakbuhin ang app"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Magtakda ng oras"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Itakda ang petsa"</string> <string name="date_time_set" msgid="5777075614321087758">"Itakda"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Tapos na"</string> <string name="default_permission_group" msgid="2690160991405646128">"Default"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"BAGO: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Walang mga kinakailangang pahintulot"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Pindutin upang huwag paganahin ang pag-debug ng USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Pumili ng pamamaraan ng pag-input"</string> <string name="configure_input_methods" msgid="9091652157722495116">"I-set up paraan ng pag-input"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"mga kandidato"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Magdagdag ng account"</string> <string name="choose_account_text" msgid="6303348737197849675">"Aling account ang nais mong gamitin?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Magdagdag ng account"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Dagdagan"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Bawasan"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> pindutin nang matagal."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Mag-slide pataas upang magdagdag at pababa upang magbawas."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Dagdagan ang minuto"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Bawasan ang minuto"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Dagdagan ang oras"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Bawasan ang oras"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Itakda ang PM"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Itakda ang AM"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Dagdagan ang buwan"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Bawasan ang buwan"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Dagdagan ang araw"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Bawasan ang araw"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Dagdagdan ang taon"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Bawasan ang taon"</string> <string name="checkbox_checked" msgid="7222044992652711167">"nilagyan ng check"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"hindi nilagyan ng check"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"pinili"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Ibahagi sa"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Ibahagi sa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Hawakan sa pag-slide. Pindutin nang matagal."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Mag-slide pataas para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Mag-slide pababa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Mag-slide pakaliwa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Mag-slide pakanan para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"I-unlock"</string> <string name="description_target_camera" msgid="969071997552486814">"Camera"</string> <string name="description_target_silent" msgid="893551287746522182">"Tahimik"</string> <string name="description_target_soundon" msgid="30052466675500172">"I-on ang tunog"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Maghanap"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Mag-swipe upang i-unlock."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Mag-plug in ng isang headset upang marinig ang mga password key na binabanggit."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot."</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 7c01fa3..959d8bd 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Uygulamaya, istediği zaman ekran dönüşünü değiştirme izni verir. Normal uygulamalar için gerekli değildir."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"işaretçi hızını değiştir"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Uygulamaya, istediği zaman fare veya izleme yüzeyi işaretçi hızını değiştirme izni verir. Normal uygulamalar için gerekli değildir."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"uygulamalara Linux sinyalleri gönder"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Uygulamaya, sağlanan sinyalin tüm kalıcı işlemlere gönderilmesini isteme izni verir."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"uygulamayı her zaman çalıştır"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Saati ayarla"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarla"</string> <string name="date_time_set" msgid="5777075614321087758">"Ayarla"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Tamamlandı"</string> <string name="default_permission_group" msgid="2690160991405646128">"Varsayılan"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"YENİ: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"İzin gerektirmez"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"USB hata ayıklama özelliğini devre dışı bırakmak için dokunun."</string> <string name="select_input_method" msgid="4653387336791222978">"Giriş yöntemini seçin"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Giriş yöntemlerini ayarla"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"adaylar"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Hesap ekleyin"</string> <string name="choose_account_text" msgid="6303348737197849675">"Hangi hesabı kullanmak istiyorsunuz?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Hesap ekle"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Artır"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Azalt"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> rakamına dokunun ve basılı tutun."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Artırmak için yukarı, azaltmak için aşağı kaydırın."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Dakikayı artır"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Dakikayı azalt"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Saati artır"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Saati azalt"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"ÖS değerini ayarla"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"ÖÖ değerini ayarla"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Ayı artır"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Ayı azalt"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Günü artır"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Günü azalt"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Yılı artır"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Yılı azalt"</string> <string name="checkbox_checked" msgid="7222044992652711167">"işaretli"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"işaretlenmedi"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"seçili"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Şununla paylaş:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ile paylaş"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Kayan tutma yeri. Dokunun ve basılı tutun."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı kaydırın."</string> + <string name="description_direction_down" msgid="5087739728639014595">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için aşağı kaydırın."</string> + <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sola kaydırın."</string> + <string name="description_direction_right" msgid="8034433242579600980">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sağa kaydırın."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Kilidi aç"</string> <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Sessiz"</string> <string name="description_target_soundon" msgid="30052466675500172">"Ses açık"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Ara"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Kilidi açmak için kaydırın."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Şifre tuşlarının sesli okunmasını dinlemek için mikrofonlu kulaklık takın."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Nokta."</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 4b3fb11..f9d372e 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Дозволяє програмі будь-коли змінювати обертання екрана. Ніколи не застосовується для звичайних програм."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"змінювати швидкість указівника"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Дозволяє програмі будь-коли змінювати швидкість вказівника миші чи сенсорної панелі. Ніколи не застосовується для звичайних програм."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"надсилати сигнали Linux програмам"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Дозволяє програмі подавати запит щодо надсилання наданого сигналу всім сталим процесам."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"заставляти програму постійно функціонувати"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Установити час"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Установити дату"</string> <string name="date_time_set" msgid="5777075614321087758">"Застосувати"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Готово"</string> <string name="default_permission_group" msgid="2690160991405646128">"За умовч."</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВИЙ: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Дозвіл не потрібний"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Торкніться, щоб вимкнути налагодження USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Вибрати метод введення"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Налаштувати методи введення"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"кандидати"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Додати обліковий запис"</string> <string name="choose_account_text" msgid="6303348737197849675">"Який обліковий запис використовувати?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Додати облік. запис"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Збільшити"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Зменшити"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> – торкніться й утримуйте."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Проведіть пальцем угору, щоб збільшити, і вниз, щоб зменшити."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"На хвилину вперед"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"На хвилину назад"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"На годину вперед"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"На годину назад"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Установити час \"пп\""</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Установити час \"дп\""</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"На місяць уперед"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"На місяць назад"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"На день уперед"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"На день назад"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"На рік уперед"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"На рік назад"</string> <string name="checkbox_checked" msgid="7222044992652711167">"перевірено"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"не перевірено"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"вибрано"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Надіслати через"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Надіслати через <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Вказівник-повзунок. Торкніться й утримуйте."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Проведіть пальцем униз, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Проведіть пальцем праворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Розблокувати"</string> <string name="description_target_camera" msgid="969071997552486814">"Камера"</string> <string name="description_target_silent" msgid="893551287746522182">"Без звуку"</string> <string name="description_target_soundon" msgid="30052466675500172">"Увімкнути звук"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Пошук"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Гортайте, щоб розблокувати."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Підключіть гарнітуру, щоб прослухати відтворені вголос символи пароля."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Крапка."</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index faa0092..dde1ad4 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Cho phép ứng dụng thay đổi độ xoay màn hình bất cứ lúc nào. Không cần thiết cho các ứng dụng thông thường."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"thay đổi tốc độ con trỏ"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Cho phép ứng dụng thay đổi tốc độ của chuột hoặc con trỏ trên ô di chuột bất kỳ lúc nào. Không cần thiết cho các ứng dụng thông thường."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"gửi tín hiệu Linux đến ứng dụng"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Cho phép ứng dụng yêu cầu tín hiệu đã cung cấp được gửi đến tất cả các quá trình liên tục."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"đặt ứng dụng luôn chạy"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Đặt giờ"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Đặt ngày"</string> <string name="date_time_set" msgid="5777075614321087758">"Đặt"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Xong"</string> <string name="default_permission_group" msgid="2690160991405646128">"Mặc định"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"MỚI: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Không yêu cầu quyền"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Chạm để vô hiệu hóa gỡ lỗi USB."</string> <string name="select_input_method" msgid="4653387336791222978">"Chọn phương thức nhập"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Thiết lập phương thức nhập"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"ứng viên"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Thêm tài khoản"</string> <string name="choose_account_text" msgid="6303348737197849675">"Bạn muốn sử dụng tài khoản nào?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Thêm tài khoản"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Tăng"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Giảm"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Chạm và giữ <xliff:g id="VALUE">%s</xliff:g>."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Trượt lên để tăng và trượt xuống để giảm."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Tăng phút"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Giảm phút"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Tăng giờ"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Giảm giờ"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Đặt CH"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Đặt SA"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Tăng tháng"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Giảm tháng"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Tăng ngày"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Giảm ngày"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Tăng năm"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Giảm năm"</string> <string name="checkbox_checked" msgid="7222044992652711167">"đã kiểm tra"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"chưa chọn"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"đã chọn"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Chia sẻ với"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Chia sẻ với <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Tay trượt. Chạm & giữ."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Trượt lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Trượt xuống để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Trượt sang trái để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Trượt sang phải để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Mở khóa"</string> <string name="description_target_camera" msgid="969071997552486814">"Máy ảnh"</string> <string name="description_target_silent" msgid="893551287746522182">"Im lặng"</string> <string name="description_target_soundon" msgid="30052466675500172">"Bật âm thanh"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Tìm kiếm"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Trượt để mở khóa."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Cắm tai nghe để nghe các khóa mật khẩu được đọc."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dấu chấm."</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 9418e38..0c338bb 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"允许应用随时更改屏幕的旋转状态。普通应用绝不需要此权限。"</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"更改指针速度"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"允许应用随时更改鼠标或触控板指针速度。普通应用绝不需要此权限。"</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"向应用发送 Linux 信号"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"允许应用请求将提供的信号发送给所有持续的进程。"</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"让应用始终运行"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"设置时间"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"设置日期"</string> <string name="date_time_set" msgid="5777075614321087758">"设置"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"完成"</string> <string name="default_permission_group" msgid="2690160991405646128">"默认"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"新增:"</font></string> <string name="no_permissions" msgid="7283357728219338112">"不需要任何权限"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"触摸以停用 USB 调试。"</string> <string name="select_input_method" msgid="4653387336791222978">"选择输入法"</string> <string name="configure_input_methods" msgid="9091652157722495116">"设置输入法"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"候选"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"添加帐户"</string> <string name="choose_account_text" msgid="6303348737197849675">"您要使用哪个帐户?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"添加帐户"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"增大"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"减小"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"触摸 <xliff:g id="VALUE">%s</xliff:g> 次并按住。"</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"向上滑动可增大数值,向下滑动可减小数值。"</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"增大分钟值"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"减小分钟值"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"增大小时值"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"减小小时值"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"设置下午时间"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"设置上午时间"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"增大月份值"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"减小月份值"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"增大日期值"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"减小日期值"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"增大年份值"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"减小年份值"</string> <string name="checkbox_checked" msgid="7222044992652711167">"已选中"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"未选中"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"已选择"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"共享对象"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"与“<xliff:g id="APPLICATION_NAME">%s</xliff:g>”共享"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"滑动手柄。触摸并按住。"</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"向上滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> + <string name="description_direction_down" msgid="5087739728639014595">"向下滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> + <string name="description_direction_left" msgid="7207478719805562165">"向左滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> + <string name="description_direction_right" msgid="8034433242579600980">"向右滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> <string name="description_target_unlock" msgid="2228524900439801453">"解锁"</string> <string name="description_target_camera" msgid="969071997552486814">"相机"</string> <string name="description_target_silent" msgid="893551287746522182">"静音"</string> <string name="description_target_soundon" msgid="30052466675500172">"打开声音"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"搜索"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"滑动解锁。"</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"需要插入耳机才能听到密码的按键声。"</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"点。"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 57d3f7e..c36b1b5 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"允許應用程式隨時變更螢幕旋轉狀態 (一般應用程式不需使用)。"</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"變更指標速度"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"允許應用程式隨時變更滑鼠或觸控板游標的移動速度 (一般應用程式不需使用)。"</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"將 Linux 訊號傳送給應用程式"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"允許應用程式要求將提供的訊號傳送給所有持續運作中的處理程序。"</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"一律執行應用程式"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"設定時間"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string> <string name="date_time_set" msgid="5777075614321087758">"設定"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"完成"</string> <string name="default_permission_group" msgid="2690160991405646128">"預設值"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"新增:"</font></string> <string name="no_permissions" msgid="7283357728219338112">"無須許可"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string> <string name="select_input_method" msgid="4653387336791222978">"選擇輸入法"</string> <string name="configure_input_methods" msgid="9091652157722495116">"設定輸入法"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"待選項目"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"新增帳戶"</string> <string name="choose_account_text" msgid="6303348737197849675">"您要使用哪個帳戶?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"新增帳戶"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"增加"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"減少"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> 輕觸並按住。"</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"向上滑動即可增加,向下滑動即可減少。"</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"增加分鐘數"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"減少分鐘數"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"增加小時數"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"減少小時數"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"設定 PM 值"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"設定 AM 值"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"增加月數"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"減少月數"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"增加日數"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"減少日數"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"增加年數"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"減少年數"</string> <string name="checkbox_checked" msgid="7222044992652711167">"已勾選"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"尚未勾選"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"已選取"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"分享對象:"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"與「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」分享"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"滑動控制。持續輕觸。"</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> + <string name="description_direction_down" msgid="5087739728639014595">"向下滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> + <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> + <string name="description_direction_right" msgid="8034433242579600980">"向右滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string> <string name="description_target_unlock" msgid="2228524900439801453">"解除鎖定"</string> <string name="description_target_camera" msgid="969071997552486814">"相機"</string> <string name="description_target_silent" msgid="893551287746522182">"靜音"</string> <string name="description_target_soundon" msgid="30052466675500172">"開啟音效"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"搜尋"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"滑動即可解鎖。"</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"連接耳機即可聽取系統朗讀密碼按鍵。"</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"點。"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 6fe919d..3b3b1e1 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -286,6 +286,10 @@ <string name="permdesc_setOrientation" msgid="3046126619316671476">"Ivumela insiza ukuthi iguqule ukujikeleza kweskrini nganoma isiphi isikhathi. Akudingakeli izinsiza ezejwayelekile."</string> <string name="permlab_setPointerSpeed" msgid="9175371613322562934">"guqula isivinini sesikhombi"</string> <string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"Ivumela insiza ukuthi iguqule ijubane legundane noma lendawo yokukhomba ngomunwe. Akufanele kudingakele izinsiza ezijwayelekile."</string> + <!-- no translation found for permlab_setKeyboardLayout (4778731703600909340) --> + <skip /> + <!-- no translation found for permdesc_setKeyboardLayout (8480016771134175879) --> + <skip /> <string name="permlab_signalPersistentProcesses" msgid="4539002991947376659">"Thumela imifanekiso ye-Linu ezinsizeni"</string> <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"Ivumela insiza ukuthi icele ukuthi isiginali ethunyelwe idluliselwe kuzo zonke izinqubeko ezisalelayo."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"yenza insiza ukuthi ihlale isebenza"</string> @@ -1019,8 +1023,7 @@ <string name="time_picker_dialog_title" msgid="8349362623068819295">"Hlela isikhathi"</string> <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setha idethi"</string> <string name="date_time_set" msgid="5777075614321087758">"Hlela"</string> - <!-- no translation found for date_time_done (2507683751759308828) --> - <skip /> + <string name="date_time_done" msgid="2507683751759308828">"Kwenziwe"</string> <string name="default_permission_group" msgid="2690160991405646128">"Okuzenzakalelayo"</string> <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"OKUSHA: "</font></string> <string name="no_permissions" msgid="7283357728219338112">"Ayikho imvume edingekayo"</string> @@ -1060,6 +1063,10 @@ <string name="adb_active_notification_message" msgid="1016654627626476142">"Thinta ukwenza ukuthi ukudibhaga kwe-USB kungasebenzi."</string> <string name="select_input_method" msgid="4653387336791222978">"Khetha indlela yokufaka"</string> <string name="configure_input_methods" msgid="9091652157722495116">"Izilungiselelo zezindlela zokufakwayo"</string> + <!-- no translation found for use_physical_keyboard (6203112478095117625) --> + <skip /> + <!-- no translation found for hardware (7517821086888990278) --> + <skip /> <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string> <string name="candidates_style" msgid="4333913089637062257"><u>"abahlanganyeli"</u></string> @@ -1170,35 +1177,22 @@ <string name="add_account_label" msgid="2935267344849993553">"Yengeza i-akhawunti"</string> <string name="choose_account_text" msgid="6303348737197849675">"Ingabe iyiphi i-akhawunti ofuna ukuyisebenzisa?"</string> <string name="add_account_button_label" msgid="3611982894853435874">"Engeza i-akhawunti"</string> - <!-- no translation found for number_picker_increment_button (2412072272832284313) --> - <skip /> - <!-- no translation found for number_picker_decrement_button (476050778386779067) --> - <skip /> + <string name="number_picker_increment_button" msgid="2412072272832284313">"Khulisa"</string> + <string name="number_picker_decrement_button" msgid="476050778386779067">"Yehlisa"</string> <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> thinta bese ucindezela."</string> - <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) --> - <skip /> - <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) --> - <skip /> - <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) --> - <skip /> - <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) --> - <skip /> - <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) --> - <skip /> + <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"Shelelisela phezulu ukuze ungeze futhi phansi ukuze wehlise."</string> + <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Khulisa iminithi"</string> + <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Yehlisa iminithi"</string> + <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Khulisa ihora"</string> + <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Yehlisa ihora"</string> <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Setha Ntambama"</string> <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Setha Ekuseni"</string> - <!-- no translation found for date_picker_increment_month_button (5369998479067934110) --> - <skip /> - <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) --> - <skip /> - <!-- no translation found for date_picker_increment_day_button (7130465412308173903) --> - <skip /> - <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) --> - <skip /> - <!-- no translation found for date_picker_increment_year_button (6318697384310808899) --> - <skip /> - <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) --> - <skip /> + <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Khulisa inyanga"</string> + <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Yehlisa inyanga"</string> + <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Khulisa usuku"</string> + <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Yehlisa usuku"</string> + <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Khulisa unyaka"</string> + <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Yehlisa unyaka"</string> <string name="checkbox_checked" msgid="7222044992652711167">"kuhloliwe"</string> <string name="checkbox_not_checked" msgid="5174639551134444056">"akuhloliwe"</string> <string name="radiobutton_selected" msgid="8603599808486581511">"Okukhethiwe"</string> @@ -1218,20 +1212,15 @@ <string name="shareactionprovider_share_with" msgid="806688056141131819">"Yabelana no"</string> <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Yabelana no <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string> <string name="content_description_sliding_handle" msgid="415975056159262248">"Ihaambis isibambo. Thinta & ubambe."</string> - <!-- no translation found for description_direction_up (7169032478259485180) --> - <skip /> - <!-- no translation found for description_direction_down (5087739728639014595) --> - <skip /> - <!-- no translation found for description_direction_left (7207478719805562165) --> - <skip /> - <!-- no translation found for description_direction_right (8034433242579600980) --> - <skip /> + <string name="description_direction_up" msgid="7169032478259485180">"Shelelisela ngenhla ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_down" msgid="5087739728639014595">"Shelelisela ngezansi ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_left" msgid="7207478719805562165">"Shelelisela ngakwesokunxele ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> + <string name="description_direction_right" msgid="8034433242579600980">"Shelelisela ngakwesokudla ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string> <string name="description_target_unlock" msgid="2228524900439801453">"Vula"</string> <string name="description_target_camera" msgid="969071997552486814">"Ikhamera"</string> <string name="description_target_silent" msgid="893551287746522182">"Thulile"</string> <string name="description_target_soundon" msgid="30052466675500172">"Umsindo uvuliwe"</string> - <!-- no translation found for description_target_search (3091587249776033139) --> - <skip /> + <string name="description_target_search" msgid="3091587249776033139">"Sesha"</string> <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Swayipha ukuze uvule."</string> <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Plaka ku-headset ukuze uzwe okhiye bephasiwedi ezindlebeni zakho bezwakala kakhulu."</string> <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Icashazi."</string> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index d414c7f..0ac2ad7 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -948,8 +948,9 @@ permission, and it must always be granted when it is installed. If you set this to false, then in some cases the application may be installed with it being granted the permission, and it will - need to request the permission later if it needs it. --> + need to request the permission later if it needs it. <attr name="required" format="boolean" /> + --> </declare-styleable> <!-- The <code>uses-configuration</code> tag specifies @@ -992,7 +993,7 @@ don't support it. If you set this to false, then this will not impose a restriction on where the application can be installed. --> - <attr name="required" /> + <attr name="required" format="boolean" /> </declare-styleable> <!-- The <code>uses-sdk</code> tag describes the SDK features that the diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 4fde018..acf63a1 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -323,8 +323,9 @@ true here reverses that logic. --> <bool name="config_reverseDefaultRotation">false</bool> - <!-- The number of degrees to rotate the display when the keyboard is open. --> - <integer name="config_lidOpenRotation">90</integer> + <!-- The number of degrees to rotate the display when the keyboard is open. + A value of -1 means no change in orientation by default. --> + <integer name="config_lidOpenRotation">-1</integer> <!-- The number of degrees to rotate the display when the device is in a desk dock. A value of -1 means no change in orientation by default. --> @@ -370,8 +371,8 @@ <!-- Indicate whether the lid state impacts the accessibility of the physical keyboard. 0 means it doesn't, 1 means it is accessible when the lid is open, 2 means it is accessible when the lid is - closed. The default is 1. --> - <integer name="config_lidKeyboardAccessibility">1</integer> + closed. The default is 0. --> + <integer name="config_lidKeyboardAccessibility">0</integer> <!-- Indicate whether the lid state impacts the accessibility of the physical keyboard. 0 means it doesn't, 1 means it is accessible @@ -817,7 +818,7 @@ <bool name="config_allowActionMenuItemTextWithIcon">false</bool> <!-- Remote server that can provide NTP responses. --> - <string translatable="false" name="config_ntpServer">pool.ntp.org</string> + <string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string> <!-- Timeout to wait for NTP server response. --> <integer name="config_ntpTimeout">20000</integer> @@ -837,6 +838,8 @@ <!-- Name of the wimax state tracker clas --> <string name="config_wimaxStateTrackerClassname" translatable="false"></string> + <!-- enable screen saver feature --> + <bool name="config_enableDreams">false</bool> <!-- Name of screensaver components to look for if none has been chosen by the user --> <string name="config_defaultDreamComponent" translatable="false">com.google.android.deskclock/com.android.deskclock.Screensaver</string> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index ca0e913..d7def44 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -85,6 +85,8 @@ <java-symbol type="id" name="fillInIntent" /> <java-symbol type="id" name="find" /> <java-symbol type="id" name="fullscreenArea" /> + <java-symbol type="id" name="hard_keyboard_section" /> + <java-symbol type="id" name="hard_keyboard_switch" /> <java-symbol type="id" name="headers" /> <java-symbol type="id" name="hour" /> <java-symbol type="id" name="icon" /> @@ -398,8 +400,6 @@ <java-symbol type="string" name="cfTemplateNotForwarded" /> <java-symbol type="string" name="cfTemplateRegistered" /> <java-symbol type="string" name="cfTemplateRegisteredTime" /> - <java-symbol type="string" name="checkbox_checked" /> - <java-symbol type="string" name="checkbox_not_checked" /> <java-symbol type="string" name="chooseActivity" /> <java-symbol type="string" name="config_default_dns_server" /> <java-symbol type="string" name="config_ethernet_iface_regex" /> @@ -699,8 +699,6 @@ <java-symbol type="string" name="preposition_for_time" /> <java-symbol type="string" name="progress_erasing" /> <java-symbol type="string" name="progress_unmounting" /> - <java-symbol type="string" name="radiobutton_not_selected" /> - <java-symbol type="string" name="radiobutton_selected" /> <java-symbol type="string" name="relationTypeAssistant" /> <java-symbol type="string" name="relationTypeBrother" /> <java-symbol type="string" name="relationTypeChild" /> @@ -795,8 +793,6 @@ <java-symbol type="string" name="sms_control_title" /> <java-symbol type="string" name="sms_control_yes" /> <java-symbol type="string" name="submit" /> - <java-symbol type="string" name="switch_off" /> - <java-symbol type="string" name="switch_on" /> <java-symbol type="string" name="sync_binding_label" /> <java-symbol type="string" name="sync_do_nothing" /> <java-symbol type="string" name="sync_really_delete" /> @@ -818,8 +814,6 @@ <java-symbol type="string" name="time_wday" /> <java-symbol type="string" name="time_wday_date" /> <java-symbol type="string" name="today" /> - <java-symbol type="string" name="togglebutton_not_pressed" /> - <java-symbol type="string" name="togglebutton_pressed" /> <java-symbol type="string" name="tomorrow" /> <java-symbol type="string" name="twelve_hour_time_format" /> <java-symbol type="string" name="twenty_four_hour_time_format" /> @@ -1042,6 +1036,7 @@ <java-symbol type="layout" name="icon_menu_layout" /> <java-symbol type="layout" name="input_method" /> <java-symbol type="layout" name="input_method_extract_view" /> + <java-symbol type="layout" name="input_method_switch_dialog_title" /> <java-symbol type="layout" name="js_prompt" /> <java-symbol type="layout" name="list_content_simple" /> <java-symbol type="layout" name="list_menu_item_checkbox" /> @@ -1110,6 +1105,7 @@ <java-symbol type="style" name="Animation.PopupWindow" /> <java-symbol type="style" name="Animation.TypingFilter" /> <java-symbol type="style" name="Animation.TypingFilterRestore" /> + <java-symbol type="style" name="Animation.Dream" /> <java-symbol type="style" name="Theme.DeviceDefault.Dialog.Alert" /> <java-symbol type="style" name="Theme.DeviceDefault.Light.Dialog.Alert" /> <java-symbol type="style" name="Theme.Dialog.Alert" /> @@ -1129,6 +1125,7 @@ <!-- From android.policy --> <java-symbol type="anim" name="app_starting_exit" /> <java-symbol type="anim" name="lock_screen_behind_enter" /> + <java-symbol type="anim" name="lock_screen_wallpaper_behind_enter" /> <java-symbol type="anim" name="dock_top_enter" /> <java-symbol type="anim" name="dock_top_exit" /> <java-symbol type="anim" name="dock_bottom_enter" /> @@ -1262,7 +1259,6 @@ <java-symbol type="layout" name="screen_title_icons" /> <java-symbol type="string" name="abbrev_wday_month_day_no_year" /> <java-symbol type="string" name="android_upgrading_title" /> - <java-symbol type="string" name="config_defaultDreamComponent" /> <java-symbol type="string" name="faceunlock_multiple_failures" /> <java-symbol type="string" name="global_action_power_off" /> <java-symbol type="string" name="global_actions_airplane_mode_off_status" /> @@ -1449,6 +1445,7 @@ <java-symbol type="string" name="factorytest_no_action" /> <java-symbol type="string" name="factorytest_not_system" /> <java-symbol type="string" name="factorytest_reboot" /> + <java-symbol type="string" name="hardware" /> <java-symbol type="string" name="heavy_weight_notification" /> <java-symbol type="string" name="heavy_weight_notification_detail" /> <java-symbol type="string" name="input_method_binding_label" /> @@ -1471,6 +1468,7 @@ <java-symbol type="string" name="usb_cd_installer_notification_title" /> <java-symbol type="string" name="usb_mtp_notification_title" /> <java-symbol type="string" name="usb_notification_message" /> + <java-symbol type="string" name="use_physical_keyboard" /> <java-symbol type="string" name="usb_ptp_notification_title" /> <java-symbol type="string" name="vpn_text" /> <java-symbol type="string" name="vpn_text_long" /> @@ -1480,6 +1478,8 @@ <java-symbol type="style" name="Theme.Dialog.AppError" /> <java-symbol type="style" name="Theme.Toast" /> <java-symbol type="xml" name="storage_list" /> + <java-symbol type="bool" name="config_enableDreams" /> + <java-symbol type="string" name="config_defaultDreamComponent" /> <!-- From SystemUI --> <java-symbol type="anim" name="push_down_in" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 44f2ade..968b51c 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -768,6 +768,12 @@ the mouse or trackpad pointer speed at any time. Should never be needed for normal apps.</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] --> + <string name="permlab_setKeyboardLayout">change keyboard layout</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] --> + <string name="permdesc_setKeyboardLayout">Allows the app to change + the keyboard layout. Should never be needed for normal apps.</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_signalPersistentProcesses">send Linux signals to apps</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> @@ -2921,6 +2927,10 @@ <string name="select_input_method">Choose input method</string> <!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] --> <string name="configure_input_methods">Set up input methods</string> + <!-- Summary text of a toggle switch to enable/disable use of the physical keyboard in the input method selector [CHAR LIMIT=25] --> + <string name="use_physical_keyboard">Physical keyboard</string> + <!-- Title of the physical keyboard category in the input method selector [CHAR LIMIT=10] --> + <string name="hardware">Hardware</string> <string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string> <string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string> @@ -3231,30 +3241,6 @@ <!-- Description of the button to decrease the DatePicker's year value. [CHAR LIMIT=NONE] --> <string name="date_picker_decrement_year_button">Decrease year</string> - <!-- CheckBox - accessibility support --> - <!-- Description of the checked state of a CheckBox. [CHAR LIMIT=NONE] --> - <string name="checkbox_checked">checked</string> - <!-- Description of the not checked state of a CheckBox. [CHAR LIMIT=NONE] --> - <string name="checkbox_not_checked">not checked</string> - - <!-- RadioButton/CheckedTextView - accessibility support --> - <!-- Description of the selected state of a RadioButton. [CHAR LIMIT=NONE] --> - <string name="radiobutton_selected">selected</string> - <!-- Description of the not selected state of a RadioButton. [CHAR LIMIT=NONE] --> - <string name="radiobutton_not_selected">not selected</string> - - <!-- Switch - accessibility support --> - <!-- Description of the on state of a Switch. [CHAR LIMIT=NONE] --> - <string name="switch_on">on</string> - <!-- Description of the off state of a Switch. [CHAR LIMIT=NONE] --> - <string name="switch_off">off</string> - - <!-- ToggleButton - accessibility support --> - <!-- Description of the pressed state of a ToggleButton. [CHAR LIMIT=NONE] --> - <string name="togglebutton_pressed">pressed</string> - <!-- Description of the not pressed state of a ToggleButton. [CHAR LIMIT=NONE] --> - <string name="togglebutton_not_pressed">not pressed</string> - <!-- KeyboardView - accessibility support --> <!-- Description of the Alt button in a KeyboardView. [CHAR LIMIT=NONE] --> <string name="keyboardview_keycode_alt">Alt</string> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index baeb9cc..18ee2f8 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -219,6 +219,12 @@ please see styles_device_defaults.xml. <item name="windowExitAnimation">@anim/fade_out</item> </style> + <!-- Window animations for screen savers. {@hide} --> + <style name="Animation.Dream"> + <item name="windowEnterAnimation">@anim/slow_fade_in</item> + <item name="windowExitAnimation">@anim/fast_fade_out</item> + </style> + <!-- Status Bar Styles --> <style name="TextAppearance.StatusBar"> <item name="android:textAppearance">?android:attr/textAppearanceSmall</item> @@ -1158,6 +1164,7 @@ please see styles_device_defaults.xml. <item name="android:minWidth">@android:dimen/action_button_min_width</item> <item name="android:minHeight">?android:attr/actionBarSize</item> <item name="android:gravity">center</item> + <item name="android:maxLines">2</item> </style> <style name="Widget.ActionButton.Overflow"> @@ -1861,6 +1868,7 @@ please see styles_device_defaults.xml. <item name="android:paddingLeft">12dip</item> <item name="android:paddingRight">12dip</item> <item name="android:scaleType">center</item> + <item name="android:maxLines">2</item> </style> <style name="Widget.Holo.ActionButton.Overflow"> diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk index 5ba6bf9..85a77d6 100644 --- a/data/fonts/Android.mk +++ b/data/fonts/Android.mk @@ -124,8 +124,8 @@ font_src_files := \ Roboto-Bold.ttf \ Roboto-Italic.ttf \ Roboto-BoldItalic.ttf \ - DroidSansArabic.ttf \ DroidNaskh-Regular.ttf \ + DroidNaskh-Regular-Shift.ttf \ DroidSansHebrew-Regular.ttf \ DroidSansHebrew-Bold.ttf \ DroidSansThai.ttf \ diff --git a/data/fonts/DroidNaskh-Regular-Shift.ttf b/data/fonts/DroidNaskh-Regular-Shift.ttf Binary files differnew file mode 100644 index 0000000..0cb843d --- /dev/null +++ b/data/fonts/DroidNaskh-Regular-Shift.ttf diff --git a/data/fonts/fallback_fonts-ja.xml b/data/fonts/fallback_fonts-ja.xml index 62491d8..db998d3 100644 --- a/data/fonts/fallback_fonts-ja.xml +++ b/data/fonts/fallback_fonts-ja.xml @@ -34,7 +34,7 @@ <familyset> <family> <fileset> - <file>DroidSansArabic.ttf</file> + <file>DroidNaskh-Regular-Shift.ttf</file> </fileset> </family> <family> diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml index ba01947..a4b5212 100644 --- a/data/fonts/fallback_fonts.xml +++ b/data/fonts/fallback_fonts.xml @@ -34,7 +34,7 @@ <familyset> <family> <fileset> - <file>DroidSansArabic.ttf</file> + <file>DroidNaskh-Regular-Shift.ttf</file> </fileset> </family> <family> diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk index db26765..702b069 100644 --- a/data/fonts/fonts.mk +++ b/data/fonts/fonts.mk @@ -24,8 +24,8 @@ PRODUCT_PACKAGES := \ Roboto-Bold.ttf \ Roboto-Italic.ttf \ Roboto-BoldItalic.ttf \ - DroidSansArabic.ttf \ DroidNaskh-Regular.ttf \ + DroidNaskh-Regular-Shift.ttf \ DroidSansHebrew-Regular.ttf \ DroidSansHebrew-Bold.ttf \ DroidSansThai.ttf \ diff --git a/docs/html/guide/developing/debugging/ddms.jd b/docs/html/guide/developing/debugging/ddms.jd index 80b1e47..9892e49 100644 --- a/docs/html/guide/developing/debugging/ddms.jd +++ b/docs/html/guide/developing/debugging/ddms.jd @@ -128,9 +128,7 @@ parent.link=index.html classes and threads are allocating the objects. This allows you to track, in real time, where objects are being allocated when you perform certain actions in your application. This information is valuable for assessing memory usage that can affect application performance. - If you want more granular control over where allocation data is collected, use the - {@link android.os.Debug#startAllocCounting()} and {@link android.os.Debug#stopAllocCounting()} - methods.</p> + </p> <p>To track memory allocation of objects:</p> <ol> diff --git a/docs/html/guide/topics/renderscript/index.jd b/docs/html/guide/topics/renderscript/index.jd index 24b9750..b2d9f84 100644 --- a/docs/html/guide/topics/renderscript/index.jd +++ b/docs/html/guide/topics/renderscript/index.jd @@ -638,8 +638,10 @@ not generated.</p> <code>rs_program_fragment</code> and <code>rs_allocation</code>, you have to obtain an object of the corresponding Android framework class first and then call the <code>set</code> method for that structure to bind the memory to the Renderscript runtime. You cannot directly manipulate these structures -at the Renderscript runtime layer. Keep in mind that user-defined structures -cannot contain pointers, so this restriction only applies to certain structures that are provided by Renderscript. +at the Renderscript runtime layer. This restriction is not applicable to user-defined structures +that contain pointers, because they cannot be exported to a reflected layer class +in the first place. A compiler error is generated if you try to declare a non-static, global +struct that contains a pointer. </p> <p>Renderscript also has support for pointers, but you must explicitly allocate the memory in your diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd index 4dc915f..8af4a1c 100644 --- a/docs/html/guide/topics/ui/declaring-layout.jd +++ b/docs/html/guide/topics/ui/declaring-layout.jd @@ -194,7 +194,7 @@ contains property types that define the size and position for each child view, a appropriate for the view group. As you can see in figure 1, the parent view group defines layout parameters for each child view (including the child view group).</p> -<img src="{@docRoot}images/layoutparams.png" alt="" height="300" align="center"/> +<img src="{@docRoot}images/layoutparams.png" alt="" /> <p class="img-caption"><strong>Figure 1.</strong> Visualization of a view hierarchy with layout parameters associated with each view.</p> diff --git a/docs/html/guide/topics/ui/index.jd b/docs/html/guide/topics/ui/index.jd index 83c8150..45c9ac9 100644 --- a/docs/html/guide/topics/ui/index.jd +++ b/docs/html/guide/topics/ui/index.jd @@ -51,7 +51,7 @@ as shown in the diagram below. This hierarchy tree can be as simple or complex a can build it up using Android's set of predefined widgets and layouts, or with custom Views that you create yourself.</p> -<img src="{@docRoot}images/viewgroup.png" alt="" width="312" height="211" align="center"/> +<img src="{@docRoot}images/viewgroup.png" alt="" /> <p> In order to attach the view hierarchy tree to the screen for rendering, your Activity must call the diff --git a/docs/html/guide/topics/wireless/wifip2p.jd b/docs/html/guide/topics/wireless/wifip2p.jd index ec8e71e..82c9abd 100644 --- a/docs/html/guide/topics/wireless/wifip2p.jd +++ b/docs/html/guide/topics/wireless/wifip2p.jd @@ -491,10 +491,10 @@ manager.connect(channel, config, new ActionListener() { </ol> <p>The following example, modified from the <a href= - "{@docRoot}resources/samples/WifiDirectDemo/index.html">Wi-Fi Direct Demo</a> sample, shows you how + "{@docRoot}resources/samples/WiFiDirectDemo/index.html">Wi-Fi Direct Demo</a> sample, shows you how to create this client-server socket communication and transfer JPEG images from a client to a server with a service. For a complete working example, compile and run the <a href= - "{@docRoot}resources/samples/WifiDirectDemo/index.html">Wi-Fi Direct Demo</a> sample.</p> + "{@docRoot}resources/samples/WiFiDirectDemo/index.html">Wi-Fi Direct Demo</a> sample.</p> <pre> public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> { diff --git a/docs/html/images/layoutparams.png b/docs/html/images/layoutparams.png Binary files differindex 7473dcc..d99625e 100644 --- a/docs/html/images/layoutparams.png +++ b/docs/html/images/layoutparams.png diff --git a/docs/html/images/training/basics/intents-choice.png b/docs/html/images/training/basics/intents-choice.png Binary files differnew file mode 100644 index 0000000..f99596d --- /dev/null +++ b/docs/html/images/training/basics/intents-choice.png diff --git a/docs/html/images/training/firstapp/adt-firstapp-setup.png b/docs/html/images/training/firstapp/adt-firstapp-setup.png Binary files differnew file mode 100644 index 0000000..c092562 --- /dev/null +++ b/docs/html/images/training/firstapp/adt-firstapp-setup.png diff --git a/docs/html/images/training/firstapp/edittext_gravity.png b/docs/html/images/training/firstapp/edittext_gravity.png Binary files differnew file mode 100644 index 0000000..f78e676 --- /dev/null +++ b/docs/html/images/training/firstapp/edittext_gravity.png diff --git a/docs/html/images/training/firstapp/edittext_wrap.png b/docs/html/images/training/firstapp/edittext_wrap.png Binary files differnew file mode 100644 index 0000000..156776d --- /dev/null +++ b/docs/html/images/training/firstapp/edittext_wrap.png diff --git a/docs/html/images/training/firstapp/firstapp.png b/docs/html/images/training/firstapp/firstapp.png Binary files differnew file mode 100644 index 0000000..d69cd20 --- /dev/null +++ b/docs/html/images/training/firstapp/firstapp.png diff --git a/docs/html/images/viewgroup.png b/docs/html/images/viewgroup.png Binary files differindex a4c2518..2c86ddb 100644 --- a/docs/html/images/viewgroup.png +++ b/docs/html/images/viewgroup.png diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd index 6f06de3..fddbcc7 100644 --- a/docs/html/sdk/ndk/index.jd +++ b/docs/html/sdk/ndk/index.jd @@ -62,7 +62,7 @@ padding: .25em 1em; <div class="toggleable open"> <a href="#" onclick="return toggleDiv(this)"><img src= "{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px"> - Android NDK, Revision 7c</a> <em>(March 2012)</em> + Android NDK, Revision 7c</a> <em>(April 2012)</em> <div class="toggleme"> <p>This release of the NDK includes an important fix for Tegra2-based devices, and a few diff --git a/docs/html/sdk/ndk/overview.jd b/docs/html/sdk/ndk/overview.jd index c98e600..d2a9746 100644 --- a/docs/html/sdk/ndk/overview.jd +++ b/docs/html/sdk/ndk/overview.jd @@ -270,11 +270,11 @@ page.title=What is the NDK? <ul> <li>If you are developing in Eclipse with ADT, use the New Project Wizard to create a new Android project for each sample, using the "Import from Existing Source" option and importing - the source from <code><ndk>/apps/<app_name>/project/</code>. Then, set up an AVD, + the source from <code><ndk>/samples/<name>/</code>. Then, set up an AVD, if necessary, and build/run the application in the emulator.</li> <li>If you are developing with Ant, use the <code>android</code> tool to create the build file - for each of the sample projects at <code><ndk>/apps/<app_name>/project/</code>. + for each of the sample projects at <code><ndk>/samples/<name>/</code>. Then set up an AVD, if necessary, build your project in the usual way, and run it in the emulator.</li> diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 3aafea9..a70b0f3 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -191,9 +191,7 @@ <span style="display:none" class="zh-TW"></span> </span> <ul> - <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r7c</a> - <span class="new">new!</span> - </li> + <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r7c</a></li> <li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li> </ul> </li> diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd new file mode 100644 index 0000000..847163a --- /dev/null +++ b/docs/html/training/basics/firstapp/building-ui.jd @@ -0,0 +1,363 @@ +page.title=Building a Simple User Interface +parent.title=Building Your First App +parent.link=index.html + +trainingnavtop=true +previous.title=Running Your App +previous.link=running-app.html +next.title=Starting Another Activity +next.link=starting-activity.html + +@jd:body + + +<!-- This is the training bar --> +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to</h2> + +<ol> + <li><a href="#LinearLayout">Use a Linear Layout</a></li> + <li><a href="#TextInput">Add a Text Input Box</a></li> + <li><a href="#Strings">Add String Resources</a></li> + <li><a href="#Button">Add a Button</a></li> + <li><a href="#Weight">Make the Input Box Fill in the Screen Width</a></li> +</ol> + + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a></li> +</ul> + + +</div> +</div> + + + +<p>The graphical user interface for an Android app is built using a hierarchy of {@link +android.view.View} and {@link android.view.ViewGroup} objects. {@link android.view.View} objects are +usually UI widgets such as a button or text field and {@link android.view.ViewGroup} objects are +invisible view containers that define how the child views are laid out, such as in a +grid or a vertical list.</p> + +<p>Android provides an XML vocabulary that corresponds to the subclasses of {@link +android.view.View} and {@link android.view.ViewGroup} so you can define your UI in XML with a +hierarchy of view elements.</p> + + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h2>Alternative Layouts</h2> + <p>Separating the UI layout into XML files is important for several reasons, +but it's especially important on Android because it allows you to define alternative layouts for +different screen sizes. For example, you can create two versions of a layout and tell +the system to use one on "small" screens and the other on "large" screens. For more information, +see the class about <a +href="{@docRoot}training/supporting-hardware/index.html">Supporting Various Hardware</a>.</p> +</div> +</div> + +<img src="{@docRoot}images/viewgroup.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> Illustration of how {@link +android.view.ViewGroup} objects form branches in the layout and contain {@link +android.view.View} objects.</p> + +<p>In this lesson, you'll create a layout in XML that includes a text input field and a +button. In the following lesson, you'll respond when the button is pressed by sending the +content of the text field to another activity.</p> + + + +<h2 id="LinearLayout">Use a Linear Layout</h2> + +<p>Open the <code>main.xml</code> file from the <code>res/layout/</code> +directory (every new Android project includes this file by default).</p> + +<p class="note"><strong>Note:</strong> In Eclipse, when you open a layout file, you’re first shown +the ADT Layout Editor. This is an editor that helps you build layouts using WYSIWYG tools. For this +lesson, you’re going to work directly with the XML, so click the <em>main.xml</em> tab at +the bottom of the screen to open the XML editor.</p> + +<p>By default, the <code>main.xml</code> file includes a layout with a {@link +android.widget.LinearLayout} root view group and a {@link android.widget.TextView} child view. +You’re going to re-use the {@link android.widget.LinearLayout} in this lesson, but change its +contents and layout orientation.</p> + +<p>First, delete the {@link android.widget.TextView} element and change the value +<a href="{@docRoot}reference/android/widget/LinearLayout.html#attr_android:orientation">{@code +android:orientation}</a> to be <code>"horizontal"</code>. The result looks like this:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="horizontal" > +</LinearLayout> +</pre> + +<p>{@link android.widget.LinearLayout} is a view group (a subclass of {@link +android.view.ViewGroup}) that lays out child views in either a vertical or horizontal orientation, +as specified by the <a +href="{@docRoot}reference/android/widget/LinearLayout.html#attr_android:orientation">{@code +android:orientation}</a> attribute. Each child of a {@link android.widget.LinearLayout} appears on +the screen in the order in which it appears in the XML.</p> + +<p>The other two attributes, <a +href="{@docRoot}reference/android/view/View.html#attr_android:layout_width">{@code +android:layout_width}</a> and <a +href="{@docRoot}reference/android/view/View.html#attr_android:layout_height">{@code +android:layout_height}</a>, are required for all views in order to specify their size.</p> + +<p>Because the {@link android.widget.LinearLayout} is the root view in the layout, it should fill +the entire screen area that's +available to the app by setting the width and height to +<code>"fill_parent"</code>.</p> + +<p class="note"><strong>Note:</strong> Beginning with Android 2.2 (API level 8), +<code>"fill_parent"</code> has been renamed <code>"match_parent"</code> to better reflect the +behavior. The reason is that if you set a view to <code>"fill_parent"</code> it does not expand to +fill the remaining space after sibling views are considered, but instead expands to +<em>match</em> the size of the parent view no matter what—it will overlap any sibling +views.</p> + +<p>For more information about layout properties, see the <a +href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layout</a> guide.</p> + + + +<h2 id="TextInput">Add a Text Input Box</h2> + +<p>To create a user-editable text box, add an {@link android.widget.EditText +<EditText>} element inside the {@link android.widget.LinearLayout <LinearLayout>}. The {@link +android.widget.EditText} class is a subclass of {@link android.view.View} that displays an editable +text box.</p> + +<p>Like every {@link android.view.View} object, you must define certain XML attributes to specify +the {@link android.widget.EditText} object's properties. Here’s how you should declare it +inside the {@link android.widget.LinearLayout <LinearLayout>} element:</p> + +<pre> + <EditText android:id="@+id/edit_message" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:hint="@string/edit_message" /> +</pre> + + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>About resource objects</h3> + <p>A resource object is simply a unique integer name that's associated with an app resource, +such as a bitmap, layout file, or string.</p> + <p>Every resource has a +corresponding resource object defined in your project's {@code gen/R.java} file. You can use the +object names in the {@code R} class to refer to your resources, such as when you need to specify a +string value for the <a +href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">{@code android:hint}</a> +attribute. You can also create arbitrary resource IDs that you associate with a view using the <a +href="{@docRoot}reference/android/view/View.html#attr_android:id">{@code android:id}</a> attribute, +which allows you to reference that view from other code.</p> + <p>The SDK tools generate the {@code R.java} each time you compile your app. You should never +modify this file by hand.</p> +</div> +</div> + +<p>About these attributes:</p> + +<dl> +<dt><a href="{@docRoot}reference/android/view/View.html#attr_android:id">{@code android:id}</a></dt> +<dd>This provides a unique identifier for the view, which you can use to reference the object +from your app code, such as to read and manipulate the object (you'll see this in the next +lesson). + +<p>The at-symbol (<code>@</code>) is required when you want to refer to a resource object from +XML, followed by the resource type ({@code id} in this case), then the resource name ({@code +edit_message}). (Other resources can use the same name as long as they are not the same +resource type—for example, the string resource uses the same name.)</p> + +<p>The plus-symbol (<code>+</code>) is needed only when you're defining a resource ID for the +first time. It tells the SDK tools that the resource ID needs to be created. Thus, when the app is +compiled, the SDK tools use the ID value, <code>edit_message</code>, to create a new identifier in +your project's {@code gen/R.java} file that is now assiciated with the {@link +android.widget.EditText} element. Once the resource ID is created, other references to the ID do not +need the plus symbol. See the sidebox for more information about resource objects.</p></dd> + +<dt><a +href="{@docRoot}reference/android/view/View.html#attr_android:layout_width">{@code +android:layout_width}</a> and <a +href="{@docRoot}reference/android/view/View.html#attr_android:layout_height">{@code +android:layout_height}</a></dt> +<dd>Instead of using specific sizes for the width and height, the <code>"wrap_content"</code> value +specifies that the view should be only as big as needed to fit the contents of the view. If you +were to instead use <code>"fill_parent"</code>, then the {@link android.widget.EditText} +element would fill the screen, because it'd match the size of the parent {@link +android.widget.LinearLayout}. For more information, see the <a +href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a> guide.</dd> + +<dt><a +href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">{@code +android:hint}</a></dt> +<dd>This is a default string to display when the text box is empty. Instead of using a hard-coded +string as the value, the value given in this example refers to a string resource. When you add the +{@code +"@string/edit_message"} value, you’ll see a compiler error because there’s no matching string +resource by that name. You'll fix this in the next section by defining the string +resource.</dd> +</dl> + + + +<h2 id="Strings">Add String Resources</h2> + +<p>When you need to add text in the user interface, you should always specify each string of text in +a resource file. String resources allow you to maintain a single location for all string +values, which makes it easier to find and update text. Externalizing the strings also allows you to +localize your app to different languages by providing alternative definitions for each +string.</p> + +<p>By default, your Android project includes a string resource file at +<code>res/values/strings.xml</code>. Open this file, delete the existing <code>"hello"</code> +string, and add one for the +<code>"edit_message"</code> string used by the {@link android.widget.EditText <EditText>} +element.</p> + +<p>While you’re in this file, also add a string for the button you’ll soon add, called +<code>"button_send"</code>.</p> + +<p>The result for <code>strings.xml</code> looks like this:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_name">My First App</string> + <string name="edit_message">Enter a message</string> + <string name="button_send">Send</string> +</resources> +</pre> + +<p>For more information about using string resources to localize your app for several languages, +see the <a +href="{@docRoot}training/basics/supporting-devices/index.html">Supporting Various Devices</a> +class.</p> + + + + +<h2 id="Button">Add a Button</h2> + +<p>Now add a {@link android.widget.Button <Button>} to the layout, immediately following the +{@link android.widget.EditText <EditText>} element:</p> + +<pre> + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/button_send" /> +</pre> + +<p>The height and width are set to <code>"wrap_content"</code> so the button is only as big as +necessary to fit the button's text.</p> + + + +<h2 id="Weight">Make the Input Box Fill in the Screen Width</h2> + +<p>The layout is currently designed so that both the {@link android.widget.EditText} and {@link +android.widget.Button} widgets are only as big as necessary to fit their content, as shown in +figure 2.</p> + +<img src="{@docRoot}images/training/firstapp/edittext_wrap.png" /> +<p class="img-caption"><strong>Figure 2.</strong> The {@link android.widget.EditText} and {@link +android.widget.Button} widgets have their widths set to +<code>"wrap_content"</code>.</p> + +<p>This works fine for the button, but not as well for the text box, because the user might type +something longer and there's extra space left on the screen. So, it'd be nice to fill that width +using the text box. +{@link android.widget.LinearLayout} enables such a design with the <em>weight</em> property, which +you can specify using the <a +href="{@docRoot}reference/android/widget/LinearLayout.LayoutParams.html#weight">{@code +android:layout_weight}</a> attribute.</p> + +<p>The weight value allows you to specify the amount of remaining space each view should consume, +relative to the amount consumed by sibling views, just like the ingredients in a drink recipe: "2 +parts vodka, 1 part coffee liquer" means two-thirds of the drink is vodka. For example, if you give +one view a weight of 2 and another one a weight of 1, the sum is 3, so the first view gets 2/3 of +the remaining space and the second view gets the rest. If you give a third view a weight of 1, +then the first view now gets 1/2 the remaining space, while the remaining two each get 1/4.</p> + +<p>The default weight for all views is 0, so if you specify any weight value +greater than 0 to only one view, then that view fills whatever space remains after each view is +given the space it requires. So, to fill the remaining space with the {@link +android.widget.EditText} element, give it a weight of 1 and leave the button with no weight.</p> + +<pre> + <EditText + android:layout_weight="1" + ... /> +</pre> + +<p>In order to improve the layout efficiency when you specify the weight, you should change the +width of the {@link android.widget.EditText} to be +zero (0dp). Setting the width to zero improves layout performance because using +<code>"wrap_content"</code> as the width requires the system to calculate a width that is +ultimately irrelevant because the weight value requires another width calculation to fill the +remaining space.</p> +<pre> + <EditText + android:layout_weight="1" + android:layout_width="0dp" + ... /> +</pre> + +<p>Figure 3 +shows the result when you assign all weight to the {@link android.widget.EditText} element.</p> + +<img src="{@docRoot}images/training/firstapp/edittext_gravity.png" /> +<p class="img-caption"><strong>Figure 3.</strong> The {@link android.widget.EditText} widget is +given all the layout weight, so fills the remaining space in the {@link +android.widget.LinearLayout}.</p> + +<p>Here’s how your complete layout file should now look:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="horizontal"> + <EditText android:id="@+id/edit_message" + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:hint="@string/edit_message" /> + <Button android:id="@+id/button_send" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/button_send" /> +</LinearLayout> +</pre> + +<p>This layout is applied by the default {@link android.app.Activity} class +that the SDK tools generated when you created the project, so you can now run the app to see the +results:</p> + +<ul> + <li>In Eclipse, click <strong>Run</strong> from the toolbar.</li> + <li>Or from a command line, change directories to the root of your Android project and +execute: +<pre> +ant debug +adb install bin/MyFirstApp-debug.apk +</pre></li> +</ul> + +<p>Continue to the next lesson to learn how you can respond to button presses, read content +from the text field, start another activity, and more.</p> + + + diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd new file mode 100644 index 0000000..5a89f2e --- /dev/null +++ b/docs/html/training/basics/firstapp/creating-project.jd @@ -0,0 +1,142 @@ +page.title=Creating an Android Project +parent.title=Building Your First App +parent.link=index.html + +trainingnavtop=true +next.title=Running Your App +next.link=running-app.html + +@jd:body + + +<!-- This is the training bar --> +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to</h2> + +<ol> + <li><a href="#Eclipse">Create a Project with Eclipse</a></li> + <li><a href="#CommandLine">Create a Project with Command Line Tools</a></li> +</ol> + +<h2>You should also read</h2> + +<ul> + <li><a href="{@docRoot}sdk/installing.html">Installing the +SDK</a></li> + <li><a href="{@docRoot}guide/developing/projects/index.html">Managing Projects</a></li> +</ul> + + +</div> +</div> + +<p>An Android project contains all the files that comprise the source code for your Android +app. The Android SDK tools make it easy to start a new Android project with a set of +default project directories and files.</p> + +<p>This lesson +shows how to create a new project either using Eclipse (with the ADT plugin) or using the +SDK tools from a command line.</p> + +<p class="note"><strong>Note:</strong> You should already have the Android SDK installed, and if +you're using Eclipse, you should have installed the <a +href="{@docRoot}sdk/eclipse-adt.html">ADT plugin</a> as well. If you have not installed +these, see <a href="{@docRoot}sdk/installing.html">Installing the Android SDK</a> and return here +when you've completed the installation.</p> + + +<h2 id="Eclipse">Create a Project with Eclipse</h2> + +<div class="figure" style="width:416px"> +<img src="{@docRoot}images/training/firstapp/adt-firstapp-setup.png" alt="" /> +<p class="img-caption"><strong>Figure 1.</strong> The new project wizard in Eclipse.</p> +</div> + +<ol> + <li>In Eclipse, select <strong>File > New > Project</strong>. +The resulting dialog should have a folder labeled <em>Android</em>. (If you don’t see the +<em>Android</em> folder, +then you have not installed the ADT plugin—see <a +href="{@docRoot}sdk/eclipse-adt.html#installing">Installing the ADT Plugin</a>).</li> + <li>Open the <em>Android</em> folder, select <em>Android Project</em> and click +<strong>Next</strong>.</li> + <li>Enter a project name (such as "MyFirstApp") and click <strong>Next</strong>.</li> + <li>Select a build target. This is the platform version against which you will compile your app. +<p>We recommend that you select the latest version possible. You can still build your app to +support older versions, but setting the build target to the latest version allows you to +easily optimize your app for a great user experience on the latest Android-powered devices.</p> +<p>If you don't see any built targets listed, you need to install some using the Android SDK +Manager tool. See <a href="{@docRoot}sdk/installing.html#AddingComponents">step 4 in the +installing guide</a>.</p> +<p>Click <strong>Next</strong>.</p></li> + <li>Specify other app details, such as the: + <ul> + <li><em>Application Name</em>: The app name that appears to the user. Enter "My First +App".</li> + <li><em>Package Name</em>: The package namespace for your app (following the same +rules as packages in the Java programming language). Your package name +must be unique across all packages installed on the Android system. For this reason, it's important +that you use a standard domain-style package name that’s appropriate to your company or +publisher entity. For +your first app, you can use something like "com.example.myapp." However, you cannot publish your +app using the "com.example" namespace.</li> + <li><em>Create Activity</em>: This is the class name for the primary user activity in your +app (an activity represents a single screen in your app). Enter "MyFirstActivity".</li> + <li><em>Minimum SDK</em>: Select <em>4 (Android 1.6)</em>. + <p>Because this version is lower than the build target selected for the app, a warning +appears, but that's alright. You simply need to be sure that you don't use any APIs that require an +<a href="{@docRoot}guide/appendix/api-levels.html">API level</a> greater than the minimum SDK +version without first using some code to verify the device's system version (you'll see this in some +other classes).</p> + </li> + </ul> + <p>Click <strong>Finish</strong>.</p> + </li> +</ol> + +<p>Your Android project is now set up with some default files and you’re ready to begin +building the app. Continue to the <a href="running-app.html">next lesson</a>.</p> + + + +<h2 id="CommandLine">Create a Project with Command Line Tools</h2> + +<p>If you're not using the Eclipse IDE with the ADT plugin, you can instead create your project +using the SDK tools in a command line:</p> + +<ol> + <li>Change directories into the Android SDK’s <code>tools/</code> path.</li> + <li>Execute: +<pre class="no-pretty-print">android list targets</pre> +<p>This prints a list of the available Android platforms that you’ve downloaded for your SDK. Find +the platform against which you want to compile your app. Make a note of the target id. We +recommend that you select the highest version possible. You can still build your app to +support older versions, but setting the build target to the latest version allows you to optimize +your app for the latest devices.</p> +<p>If you don't see any targets listed, you need to +install some using the Android SDK +Manager tool. See <a href="{@docRoot}sdk/installing.html#AddingComponents">step 4 in the +installing guide</a>.</p></li> + <li>Execute: +<pre class="no-pretty-print"> +android create project --target <target-id> --name MyFirstApp \ +--path <path-to-workspace>/MyFirstApp --activity MyFirstActivity \ +--package com.example.myapp +</pre> +<p>Replace <code><target-id></code> with an id from the list of targets (from the previous step) +and replace +<code><path-to-workspace></code> with the location in which you want to save your Android +projects.</p></li> +</ol> + +<p>Your Android project is now set up with several default configurations and you’re ready to begin +building the app. Continue to the <a href="running-app.html">next lesson</a>.</p> + +<p class="note"><strong>Tip:</strong> Add the <code>platform-tools/</code> as well as the +<code>tools/</code> directory to your <code>PATH</code> environment variable.</p> + + + + diff --git a/docs/html/training/basics/firstapp/index.jd b/docs/html/training/basics/firstapp/index.jd new file mode 100644 index 0000000..a95ed8e --- /dev/null +++ b/docs/html/training/basics/firstapp/index.jd @@ -0,0 +1,64 @@ +page.title=Building Your First App + +trainingnavtop=true +startpage=true +next.title=Creating an Android Project +next.link=creating-project.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Dependencies and prerequisites</h2> + +<ul> + <li>Android 1.6 or higher</li> + <li><a href="http://developer.android.com/sdk/index.html">Android SDK</a></li> +</ul> + +</div> +</div> + +<p>Welcome to Android application development!</p> + +<p>This class teaches you how to build your first Android app. You’ll learn how to create an Android +project and run a debuggable version of the app. You'll also learn some fundamentals of Android app +design, including how to build a simple user interface and handle user input.</p> + +<p>Before you start this class, be sure that you have your development environment set up. You need +to:</p> +<ol> + <li>Download the Android SDK Starter Package.</li> + <li>Install the ADT plugin for Eclipse (if you’ll use the Eclipse IDE).</li> + <li>Download the latest SDK tools and platforms using the SDK Manager.</li> +</ol> + +<p>If you haven't already done this setup, read <a href="{@docRoot}sdk/installing.html">Installing +the SDK</a>. Once you've finished the setup, you're ready to begin this class.</p> + +<p>This class uses a tutorial format that incrementally builds a small Android app in order to teach +you some fundamental concepts about Android development, so it's important that you follow each +step.</p> + +<p><strong><a href="creating-project.html">Start the first lesson ›</a></strong></p> + + +<h2>Lessons</h2> + +<dl> + <dt><b><a href="creating-project.html">Creating an Android Project</a></b></dt> + <dd>Shows how to create a project for an Android app, which includes a set of default +app files.</dd> + + <dt><b><a href="running-app.html">Running Your Application</a></b></dt> + <dd>Shows how to run your app on an Android-powered device or the Android +emulator.</dd> + + <dt><b><a href="building-ui.html">Building a Simple User Interface</a></b></dt> + <dd>Shows how to create a new user interface using an XML file.</dd> + + <dt><b><a href="starting-activity.html">Starting Another Activity</a></b></dt> + <dd>Shows how to respond to a button press, start another activity, send it some +data, then receive the data in the subsequent activity.</dd> +</dl> diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd new file mode 100644 index 0000000..2398fa0 --- /dev/null +++ b/docs/html/training/basics/firstapp/running-app.jd @@ -0,0 +1,178 @@ +page.title=Running Your App +parent.title=Building Your First App +parent.link=index.html + +trainingnavtop=true +previous.title=Creating a Project +previous.link=creating-project.html +next.title=Building a Simple User Interface +next.link=building-ui.html + +@jd:body + + +<!-- This is the training bar --> +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to</h2> + +<ol> + <li><a href="#RealDevice">Run on a Real Device</a></li> + <li><a href="#Emulator">Run on the Emulator</a></li> +</ol> + +<h2>You should also read</h2> + +<ul> + <li><a href="{@docRoot}guide/developing/device.html">Using Hardware Devices</a></li> + <li><a href="{@docRoot}guide/developing/devices/index.html">Managing Virtual Devices</a></li> + <li><a href="{@docRoot}guide/developing/projects/index.html">Managing Projects</a></li> +</ul> + + +</div> +</div> + + +<p>If you followed the <a href="{@docRoot}creating-project.html">previous lesson</a> to create an +Android project, it includes a default set of "Hello World" source files that allow you to +run the app right away.</p> + +<p>How you run your app depends on two things: whether you have a real Android-powered device and +whether you’re using Eclipse. This lesson shows you how to install and run your app on a +real device and on the Android emulator, and in both cases with either Eclipse or the command line +tools.</p> + +<p>Before you run your app, you should be aware of a few directories and files in the Android +project:</p> + +<dl> + <dt><code>AndroidManifest.xml</code></dt> + <dd>This manifest file describes the fundamental characteristics of the app and defines each of +its components. You'll learn about various declarations in this file as you read more training +classes.</dd> + <dt><code>src/</code></dt> + <dd>Directory for your app's main source files. By default, it includes an {@link +android.app.Activity} class that runs when your app is launched using the app icon.</dd> + <dt><code>res/</code></dt> + <dd>Contains several sub-directories for app resources. Here are just a few: + <dl style="margin-top:1em"> + <dt><code>drawable-hdpi/</code></dt> + <dd>Directory for drawable objects (such as bitmaps) that are designed for high-density +(hdpi) screens. Other drawable directories contain assets designed for other screen densities.</dd> + <dt><code>layout/</code></dt> + <dd>Directory for files that define your app's user interface.</dd> + <dt><code>values/</code></dt> + <dd>Directory for other various XML files that contain a collection of resources, such as +string and color definitions.</dd> + </dl> + </dd> +</dl> + +<p>When you build and run the default Android project, the default {@link android.app.Activity} +class in the <code>src/</code> directory starts and loads a layout file from the +<code>layout/</code> directory, which includes a "Hello World" message. Not real exciting, but it's +important that you understand how to build and run your app before adding real functionality to +the app.</p> + + + +<h2 id="RealDevice">Run on a Real Device</h2> + +<p>Whether you’re using Eclipse or the command line, you need to:</p> + +<ol> + <li>Plug in your Android-powered device to your machine with a USB cable. +If you’re developing on Windows, you might need to install the appropriate USB driver for your +device. For help installing drivers, see the <a href=”{@docRoot}sdk/oem-usb.html”>OEM USB +Drivers</a> document.</li> + <li>Ensure that <strong>USB debugging</strong> is enabled in the device Settings (open Settings +and navitage to <strong>Applications > Development</strong> on most devices, or select +<strong>Developer options</strong> on Android 4.0 and higher).</li> +</ol> + +<p>To run the app from Eclipse, open one of your project's files and click +<strong>Run</strong> from the toolbar. Eclipse installs the app on your connected device and starts +it.</p> + + +<p>Or to run your app from a command line:</p> + +<ol> + <li>Change directories to the root of your Android project and execute: +<pre class="no-pretty-print">ant debug</pre></li> + <li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your +<code>PATH</code> environment variable, then execute: +<pre class="no-pretty-print">adb install bin/MyFirstApp-debug.apk</pre></li> + <li>On your device, locate <em>MyFirstActivity</em> and open it.</li> +</ol> + +<p>To start adding stuff to the app, continue to the <a href="building-ui.html">next +lesson</a>.</p> + + + +<h2 id="Emulator">Run on the Emulator</h2> + +<p>Whether you’re using Eclipse or the command line, you need to first create an <a +href="{@docRoot}guide/developing/devices/index.html">Android Virtual +Device</a> (AVD). An AVD is a +device configuration for the Android emulator that allows you to model +different device configurations.</p> + +<div class="figure" style="width:457px"> + <img src="{@docRoot}images/screens_support/avds-config.png" alt="" /> + <p class="img-caption"><strong>Figure 1.</strong> The AVD Manager showing a few virtual +devices.</p> +</div> + +<p>To create an AVD:</p> +<ol> + <li>Launch the Android Virtual Device Manager: + <ol type="a"> + <li>In Eclipse, select <strong>Window > AVD Manager</strong>, or click the <em>AVD +Manager</em> icon in the Eclipse toolbar.</li> + <li>From the command line, change directories to <code><sdk>/tools/</code> and execute: +<pre class="no-pretty-print">./android avd</pre></li> + </ol> + </li> + <li>In the <em>Android Virtual Device Device Manager</em> panel, click <strong>New</strong>.</li> + <li>Fill in the details for the AVD. +Give it a name, a platform target, an SD card size, and a skin (HVGA is default).</li> + <li>Click <strong>Create AVD</strong>.</li> + <li>Select the new AVD from the <em>Android Virtual Device Manager</em> and click +<strong>Start</strong>.</li> + <li>After the emulator boots up, unlock the emulator screen.</li> +</ol> + +<p>To run the app from Eclipse, open one of your project's files and click +<strong>Run</strong> from the toolbar. Eclipse installs the app on your AVD and starts it.</p> + + +<p>Or to run your app from the command line:</p> + +<ol> + <li>Change directories to the root of your Android project and execute: +<pre class="no-pretty-print">ant debug</pre></li> + <li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your +<code>PATH</code> environment +variable, then execute: +<pre class="no-pretty-print">adb install bin/MyFirstApp-debug.apk</pre></li> + <li>On the emulator, locate <em>MyFirstActivity</em> and open it.</li> +</ol> + + +<p>To start adding stuff to the app, continue to the <a href="building-ui.html">next +lesson</a>.</p> + + + + + + + + + + + diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd new file mode 100644 index 0000000..16a6fd8 --- /dev/null +++ b/docs/html/training/basics/firstapp/starting-activity.jd @@ -0,0 +1,308 @@ +page.title=Starting Another Activity +parent.title=Building Your First App +parent.link=index.html + +trainingnavtop=true +previous.title=Building a Simpler User Interface +previous.link=building-ui.html + +@jd:body + + +<!-- This is the training bar --> +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to</h2> + +<ol> + <li><a href="#RespondToButton">Respond to the Send Button</a></li> + <li><a href="#BuildIntent">Build an Intent</a></li> + <li><a href="#StartActivity">Start the Second Activity</a></li> + <li><a href="#CreateActivity">Create the Second Activity</a> + <ol> + <li><a href="#AddToManifest">Add it to the manifest</a></li> + </ol> + </li> + <li><a href="#ReceiveIntent">Receive the Intent</a></li> + <li><a href="#DisplayMessage">Display the Message</a></li> +</ol> + +<h2>You should also read</h2> + +<ul> + <li><a href="{@docRoot}sdk/installing.html">Installing the +SDK</a></li> +</ul> + + +</div> +</div> + + + +<p>After completing the <a href="building-ui.html">previous lesson</a>, you have an app that +shows an activity (a single screen) with a text box and a button. In this lesson, you’ll add some +code to <code>MyFirstActivity</code> that +starts a new activity when the user selects the Send button.</p> + + +<h2 id="RespondToButton">Respond to the Send Button</h2> + +<p>To respond to the button's on-click event, open the <code>main.xml</code> layout file and add the +<a +href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a> +attribute to the {@link android.widget.Button <Button>} element:</p> + +<pre> +<Button android:id="@+id/button_send" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/button_send" + android:onClick="sendMessage" /> +</pre> + +<p>The <a +href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code +android:onClick}</a> attribute’s value, <code>sendMessage</code>, is the name of a method in your +activity that you want to call when the user selects the button.</p> + +<p>Add the corresponding method inside the <code>MyFirstActivity</code> class:</p> + +<pre> +/** Called when the user selects the Send button */ +public void sendMessage(View view) { + // Do something in response to button +} +</pre> + +<p class="note"><strong>Tip:</strong> In Eclipse, press Ctrl + Shift + O to import missing classes +(Cmd + Shift + O on Mac).</p> + +<p>Note that, in order for the system to match this method to the method name given to <a +href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a>, +the signature must be exactly as shown. Specifically, the method must:</p> + +<ul> +<li>Be public</li> +<li>Have a void return value</li> +<li>Have a {@link android.view.View} as the only parameter (this will be the {@link +android.view.View} that was clicked)</li> +</ul> + +<p>Next, you’ll fill in this method to read the contents of the text box and deliver that text to +another activity.</p> + + + +<h2 id="BuildIntent">Build an Intent</h2> + +<p>An {@link android.content.Intent} is an object that provides runtime binding between separate +components (such as two activities). The {@link android.content.Intent} represents an +app’s "intent to do something." You can use an {@link android.content.Intent} for a wide +variety of tasks, but most often they’re used to start another activity.</p> + +<p>Inside the {@code sendMessage()} method, create an {@link android.content.Intent} to start +an activity called {@code DisplayMessageActvity}:</p> + +<pre> +Intent intent = new Intent(this, DisplayMessageActivity.class); +</pre> + +<p>The constructor used here takes two parameters:</p> +<ul> + <li>A {@link +android.content.Context} as its first parameter ({@code this} is used because the {@link +android.app.Activity} class is a subclass of {@link android.content.Context}) + <li>The {@link java.lang.Class} of the app component to which the system should deliver +the {@link android.content.Intent} (in this case, the activity that should be started) +</ul> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>Sending an intent to other apps</h3> + <p>The intent created in this lesson is what's considered an <em>explicit intent</em>, because the +{@link android.content.Intent} +specifies the exact app component to which the intent should be given. However, intents +can also be <em>implicit</em>, in which case the {@link android.content.Intent} does not specify +the desired component, but allows any app installed on the device to respond to the intent +as long as it satisfies the meta-data specifications for the action that's specified in various +{@link android.content.Intent} parameters. For more informations, see the class about <a +href="{@docRoot}training/intents/index.html">Interacting with Other Apps</a>.</p> +</div> +</div> + +<p class="note"><strong>Note:</strong> The reference to {@code DisplayMessageActivity} +will raise an error if you’re using an IDE such as Eclipse because the class doesn’t exist yet. +Ignore the error for now; you’ll create the class soon.</p> + +<p>An intent not only allows you to start another activity, but can carry a bundle of data to the +activity as well. So, use {@link android.app.Activity#findViewById findViewById()} to get the +{@link android.widget.EditText} element and add its message to the intent:</p> + +<pre> +Intent intent = new Intent(this, DisplayMessageActivity.class); +EditText editText = (EditText) findViewById(R.id.edit_message); +String message = editText.getText().toString(); +intent.putExtra(EXTRA_MESSAGE, message); +</pre> + +<p>An {@link android.content.Intent} can carry a collection of various data types as key-value +pairs called <em>extras</em>. The {@link android.content.Intent#putExtra putExtra()} method takes a +string as the key and the value in the second parameter.</p> + +<p>In order for the next activity to query the extra data, you should define your keys using a +public constant. So add the {@code EXTRA_MESSAGE} definition to the top of the {@code +MyFirstActivity} class:</p> + +<pre> +public class MyFirstActivity extends Activity { + public final static String EXTRA_MESSAGE = "com.example.myapp.MESSAGE"; + ... +} +</pre> + +<p>It's generally a good practice to define keys for extras with your app's package name as a prefix +to ensure it's unique, in case your app interacts with other apps.</p> + + +<h2 id="StartActivity">Start the Second Activity</h2> + +<p>To start an activity, you simply need to call {@link android.app.Activity#startActivity +startActivity()} and pass it your {@link android.content.Intent}.</p> + +<p>The system receives this call and starts an instance of the {@link android.app.Activity} +specified by the {@link android.content.Intent}.</p> + +<p>With this method included, the complete {@code sendMessage()} method that's invoked by the Send +button now looks like this:</p> + +<pre> +/** Called when the user selects the Send button */ +public void sendMessage(View view) { + Intent intent = new Intent(this, DisplayMessageActivity.class); + EditText editText = (EditText) findViewById(R.id.edit_message); + String message = editText.getText().toString(); + intent.putExtra(EXTRA_MESSAGE, message); + startActivity(intent); +} +</pre> + +<p>Now you need to create the {@code DisplayMessageActivity} class in order for this to +work.</p> + + + +<h2 id="CreateActivity">Create the Second Activity</h2> + +<p>In your project, create a new class file under the <code>src/<package-name>/</code> +directory called <code>DisplayMessageActivity.java</code>.</p> + +<p class="note"><strong>Tip:</strong> In Eclipse, right-click the package name under the +<code>src/</code> directory and select <strong>New > Class</strong>. +Enter "DisplayMessageActivity" for the name and {@code android.app.Activity} for the superclass.</p> + +<p>Inside the class, add the {@link android.app.Activity#onCreate onCreate()} callback method:</p> + +<pre> +public class DisplayMessageActivity extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } +} +</pre> + +<p>All subclasses of {@link android.app.Activity} must implement the {@link +android.app.Activity#onCreate onCreate()} method. The system calls this when creating a new +instance of the activity. It is where you must define the activity layout and where you should +initialize essential activity components.</p> + + + +<h3 id="AddToManifest">Add it to the manifest</h3> + +<p>You must declare all activities in your manifest file, <code>AndroidManifest.xml</code>, using an +<a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element.</p> + +<p>Because {@code DisplayMessageActivity} is invoked using an explicit intent, it does not require +any intent filters (such as those you can see in the manifest for <code>MyFirstActivity</code>). So +the declaration for <code>DisplayMessageActivity</code> can be simply one line of code inside the <a +href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a> +element:</p> + +<pre> +<application ... > + <activity android:name="com.example.myapp.DisplayMessageActivity" /> + ... +</application> +</pre> + +<p>The app is now runnable because the {@link android.content.Intent} in the +first activity now resolves to the {@code DisplayMessageActivity} class. If you run the app now, +pressing the Send button starts the +second activity, but it doesn't show anything yet.</p> + + +<h2 id="ReceiveIntent">Receive the Intent</h2> + +<p>Every {@link android.app.Activity} is invoked by an {@link android.content.Intent}, regardless of +how the user navigated there. You can get the {@link android.content.Intent} that started your +activity by calling {@link android.app.Activity#getIntent()} and the retrieve data contained +within it.</p> + +<p>In the {@code DisplayMessageActivity} class’s {@link android.app.Activity#onCreate onCreate()} +method, get the intent and extract the message delivered by {@code MyFirstActivity}:</p> + +<pre> +Intent intent = getIntent(); +String message = intent.getStringExtra(MyFirstActivity.EXTRA_MESSAGE); +</pre> + + + +<h2 id="DisplayMessage">Display the Message</h2> + +<p>To show the message on the screen, create a {@link android.widget.TextView} widget and set the +text using {@link android.widget.TextView#setText setText()}. Then add the {@link +android.widget.TextView} as the root view of the activity’s layout by passing it to {@link +android.app.Activity#setContentView setContentView()}.</p> + +<p>The complete {@link android.app.Activity#onCreate onCreate()} method for {@code +DisplayMessageActivity} now looks like this:</p> + +<pre> +@Override +public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Get the message from the intent + Intent intent = getIntent(); + String message = intent.getStringExtra(MyFirstActivity.EXTRA_MESSAGE); + + // Create the text view + TextView textView = new TextView(this); + textView.setTextSize(40); + textView.setText(message); + + setContentView(textView); +} +</pre> + +<p>You can now run the app, type a message in the text box, press Send, and view the message on the +second activity.</p> + +<img src="{@docRoot}images/training/firstapp/firstapp.png" /> +<p class="img-caption"><strong>Figure 1.</strong> Both activities in the final app, running +on Android 4.0. + +<p>That's it, you've built your first Android app!</p> + +<p>To learn more about building Android apps, continue to follow the +basic training classes. The next class is <a +href="{@docRoot}training/activity-lifecycle/index.html">Managing the Activity Lifecycle</a>.</p> + + + + diff --git a/docs/html/training/basics/intents/filters.jd b/docs/html/training/basics/intents/filters.jd new file mode 100644 index 0000000..0090c98 --- /dev/null +++ b/docs/html/training/basics/intents/filters.jd @@ -0,0 +1,244 @@ +page.title=Allowing Other Apps to Start Your Activity +parent.title=Interacting with Other Apps +parent.link=index.html + +trainingnavtop=true +previous.title=Getting a Result from an Activity +previous.link=result.html + +@jd:body + +<div id="tb-wrapper"> + <div id="tb"> + +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#AddIntentFilter">Add an Intent Filter</a></li> + <li><a href="#HandleIntent">Handle the Intent in Your Activity</a></li> + <li><a href="#ReturnResult">Return a Result</a></li> +</ol> + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li> +</ul> + </div> +</div> + +<p>The previous two lessons focused on one side of the story: starting another app's activity from +your app. But if your app can perform an action that might be useful to another app, +your app should be prepared to respond to action requests from other apps. For instance, if you +build a social app that can share messages or photos with the user's friends, it's in your best +interest to support the {@link android.content.Intent#ACTION_SEND} intent so users can initiate a +"share" action from another app and launch your app to perform the action.</p> + +<p>To allow other apps to start your activity, you need to add an <a +href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a> +element in your manifest file for the corresponding <a +href="{@docRoot}guide/topics/manifest/activity-element.html">{@code <activity>}</a> element.</p> + +<p>When your app is installed on a device, the system identifies your intent +filters and adds the information to an internal catalog of intents supported by all installed apps. +When an app calls {@link android.app.Activity#startActivity +startActivity()} or {@link android.app.Activity#startActivityForResult startActivityForResult()}, +with an implicit intent, the system finds which activity (or activities) can respond to the +intent.</p> + + + +<h2 id="AddIntentFilter">Add an Intent Filter</h2> + +<p>In order to properly define which intents your activity can handle, each intent filter you add +should be as specific as possible in terms of the type of action and data the activity +accepts.</p> + +<p>The system may send a given {@link android.content.Intent} to an activity if that activity has +an intent filter fulfills the following criteria of the {@link android.content.Intent} object:</p> + +<dl> + <dt>Action</dt> + <dd>A string naming the action to perform. Usually one of the platform-defined values such +as {@link android.content.Intent#ACTION_SEND} or {@link android.content.Intent#ACTION_VIEW}. + <p>Specify this in your intent filter with the <a +href="{@docRoot}guide/topics/manifest/action-element.html">{@code <action>}</a> element. +The value you specify in this element must be the full string name for the action, instead of the +API constant (see the examples below).</p></dd> + + <dt>Data</dt> + <dd>A description of the data associated with the intent. + <p>Specify this in your intent filter with the <a +href="{@docRoot}guide/topics/manifest/data-element.html">{@code <data>}</a> element. Using one +or more attributes in this element, you can specify just the MIME type, just a URI prefix, +just a URI scheme, or a combination of these and others that indicate the data type +accepted.</p> + <p class="note"><strong>Note:</strong> If you don't need to declare specifics about the data +{@link android.net.Uri} (such as when your activity handles to other kind of "extra" data, instead +of a URI), you should specify only the {@code android:mimeType} attribute to declare the type of +data your activity handles, such as {@code text/plain} or {@code image/jpeg}.</p> +</dd> + <dt>Category</dt> + <dd>Provides an additional way to characterize the activity handling the intent, usually related +to the user gesture or location from which it's started. There are several different categories +supported by the system, but most are rarely used. However, all implicit intents are defined with +{@link android.content.Intent#CATEGORY_DEFAULT} by default. + <p>Specify this in your intent filter with the <a +href="{@docRoot}guide/topics/manifest/category-element.html">{@code <category>}</a> +element.</p></dd> +</dl> + +<p>In your intent filter, you can declare which criteria your activity accepts +by declaring each of them with corresponding XML elements nested in the <a +href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code <intent-filter>}</a> +element.</p> + +<p>For example, here's an activity with an intent filter that handles the {@link +android.content.Intent#ACTION_SEND} intent when the data type is either text or an image:</p> + +<pre> +<activity android:name="ShareActivity"> + <intent-filter> + <action android:name="android.intent.action.SEND"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="text/plain"/> + <data android:mimeType="image/*"/> + </intent-filter> +</activity> +</pre> + +<p>Each incoming intent specifies only one action and one data type, but it's OK to declare multiple +instances of the <a href="{@docRoot}guide/topics/manifest/action-element.html">{@code +<action>}</a>, <a href="{@docRoot}guide/topics/manifest/category-element.html">{@code +<category>}</a>, and <a href="{@docRoot}guide/topics/manifest/data-element.html">{@code +<data>}</a> elements in each +<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">{@code +<intent-filter>}</a>.</p> + +<p>If any two pairs of action and data are mutually exclusive in +their behaviors, you should create separate intent filters to specify which actions are acceptable +when paired with which data types.</p> + +<p>For example, suppose your activity handles both text and images for both the {@link +android.content.Intent#ACTION_SEND} and {@link +android.content.Intent#ACTION_SENDTO} intents. In this case, you must define two separate +intent filters for the two actions because a {@link +android.content.Intent#ACTION_SENDTO} intent must use the data {@link android.net.Uri} to specify +the recipient's address using the {@code send} or {@code sendto} URI scheme. For example:</p> + +<pre> +<activity android:name="ShareActivity"> + <!-- filter for sending text; accepts SENDTO action with sms URI schemes --> + <intent-filter> + <action android:name="android.intent.action.SENDTO"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:scheme="sms" /> + <data android:scheme="smsto" /> + </intent-filter> + <!-- filter for sending text or images; accepts SEND action and text or image data --> + <intent-filter> + <action android:name="android.intent.action.SEND"/> + <category android:name="android.intent.category.DEFAULT"/> + <data android:mimeType="image/*"/> + <data android:mimeType="text/plain"/> + </intent-filter> +</activity> +</pre> + +<p class="note"><strong>Note:</strong> In order to receive implicit intents, you must include the +{@link android.content.Intent#CATEGORY_DEFAULT} category in the intent filter. The methods {@link +android.app.Activity#startActivity startActivity()} and {@link +android.app.Activity#startActivityForResult startActivityForResult()} treat all intents as if they +contained the {@link android.content.Intent#CATEGORY_DEFAULT} category. If you do not declare it, no +implicit intents will resolve to your activity.</p> + +<p>For more information about sending and receiving {@link android.content.Intent#ACTION_SEND} +intents that perform social sharing behaviors, see the lesson about <a +href="{@docRoot}training/sharing/receive.html">Receiving Content from Other Apps</a>.</p> + + +<h2 id="HandleIntent">Handle the Intent in Your Activity</h2> + +<p>In order to decide what action to take in your activity, you can read the {@link +android.content.Intent} that was used to start it.</p> + +<p>As your activity starts, call {@link android.app.Activity#getIntent()} to retrieve the +{@link android.content.Intent} that started the activity. You can do so at any time during the +lifecycle of the activity, but you should generally do so during early callbacks such as +{@link android.app.Activity#onCreate onCreate()} or {@link android.app.Activity#onStart()}.</p> + +<p>For example:</p> + +<pre> +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.main); + + // Get the intent that started this activity + Intent intent = getIntent(); + Uri data = intent.getData(); + + // Figure out what to do based on the intent type + if (intent.getType().indexOf("image/") != -1) { + // Handle intents with image data ... + } else if (intent.getType().equals("text/plain")) { + // Handle intents with text ... + } +} +</pre> + + +<h2 id="ReturnResult">Return a Result</h2> + +<p>If you want to return a result to the activity that invoked yours, simply call {@link +android.app.Activity#setResult(int,Intent) setResult()} to specify the result code and result {@link +android.content.Intent}. When your operation is done and the user should return to the original +activity, call {@link android.app.Activity#finish()} to close (and destroy) your activity. For +example:</p> + +<pre> +// Create intent to deliver some kind of result data +Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"); +setResult(Activity.RESULT_OK, result); +finish(); +</pre> + +<p>You must always specify a result code with the result. Generally, it's either {@link +android.app.Activity#RESULT_OK} or {@link android.app.Activity#RESULT_CANCELED}. You can then +provide additional data with an {@link android.content.Intent}, as necessary.</p> + +<p class="note"><strong>Note:</strong> The result is set to {@link +android.app.Activity#RESULT_CANCELED} by default. So, if the user presses the <em>Back</em> +button before completing the action and before you set the result, the original activity receives +the "canceled" result.</p> + +<p>If you simply need to return an integer that indicates one of several result options, you can set +the result code to any value higher than 0. If you use the result code to deliver an integer and you +have no need to include the {@link android.content.Intent}, you can call {@link +android.app.Activity#setResult(int) setResult()} and pass only a result code. For example:</p> + +<pre> +setResult(RESULT_COLOR_RED); +finish(); +</pre> + +<p>In this case, there might be only a handful of possible results, so the result code is a locally +defined integer (greater than 0). This works well when you're returning a result to an activity +in your own app, because the activity that receives the result can reference the public +constant to determine the value of the result code.</p> + +<p class="note"><strong>Note:</strong> There's no need to check whether your activity was started +with {@link +android.app.Activity#startActivity startActivity()} or {@link +android.app.Activity#startActivityForResult startActivityForResult()}. Simply call {@link +android.app.Activity#setResult(int,Intent) setResult()} if the intent that started your activity +might expect a result. If the originating activity had called {@link +android.app.Activity#startActivityForResult startActivityForResult()}, then the system delivers it +the result you supply to {@link android.app.Activity#setResult(int,Intent) setResult()}; otherwise, +the result is ignored.</p> + + + + + + diff --git a/docs/html/training/basics/intents/index.jd b/docs/html/training/basics/intents/index.jd new file mode 100644 index 0000000..c661d98 --- /dev/null +++ b/docs/html/training/basics/intents/index.jd @@ -0,0 +1,64 @@ +page.title=Interacting with Other Apps + +trainingnavtop=true +startpage=true +next.title=Sending the User to Another App +next.link=sending.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Dependencies and prerequisites</h2> +<ul> + <li>Basic understanding of the Activity lifecycle (see <a +href="{@docRoot}training/basics/activity-lifecycle/index.html">Managing the Activity +Lifecycle</a>)</li> +</ul> + + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li> + <li><a +href="http://android-developers.blogspot.com/2009/11/integrating-application-with-intents.html"> +Integrating Application with Intents (blog post)</a></li> + <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent +Filters</a></li> +</ul> + +</div> +</div> + +<p>An Android app typically has several <a +href="{@docRoot}guide/topics/fundamentals/activities.html">activities</a>. Each activity displays a +user interface that allows the user to perform a specific task (such as view a map or take a photo). +To take the user from one activity to another, your app must use an {@link +android.content.Intent} to define your app's "intent" to do something. When you pass an +{@link android.content.Intent} to the system with a method such as {@link +android.app.Activity#startActivity startActivity()}, the system uses the {@link +android.content.Intent} to identify and start the appropriate app component. Using intents even +allows your app to start an activity that is contained in a separate app.</p> + +<p>An {@link android.content.Intent} can be <em>explicit</em> in order to start a specific component +(a specific {@link android.app.Activity} instance) or <em>implicit</em> in order to start any +component that can handle the intended action (such as "capture a photo").</p> + +<p>This class shows you how to use an {@link android.content.Intent} to perform some basic +interactions with other apps, such as start another app, receive a result from that app, and +make your app able to respond to intents from other apps.</p> + +<h2>Lessons</h2> + +<dl> + <dt><b><a href="sending.html">Sending the User to Another App</a></b></dt> + <dd>Shows how you can create implicit intents to launch other apps that can perform an +action.</dd> + <dt><b><a href="result.html">Getting a Result from an Activity</a></b></dt> + <dd>Shows how to start another activity and receive a result from the activity.</dd> + <dt><b><a href="filters.html">Allowing Other Apps to Start Your Activity</a></b></dt> + <dd>Shows how to make activities in your app open for use by other apps by defining +intent filters that declare the implicit intents your app accepts.</dd> +</dl> + diff --git a/docs/html/training/basics/intents/result.jd b/docs/html/training/basics/intents/result.jd new file mode 100644 index 0000000..0086913 --- /dev/null +++ b/docs/html/training/basics/intents/result.jd @@ -0,0 +1,182 @@ +page.title=Getting a Result from an Activity +parent.title=Interacting with Other Apps +parent.link=index.html + +trainingnavtop=true +previous.title=Sending the User to Another App +previous.link=sending.html +next.title=Allowing Other Apps to Start Your Activity +next.link=filters.html + +@jd:body + +<div id="tb-wrapper"> + <div id="tb"> + +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#StartActivity">Start the Activity</a></li> + <li><a href="#ReceiveResult">Receive the Result</a></li> +</ol> + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li> +</ul> + + </div> +</div> + +<p>Starting another activity doesn't have to be one-way. You can also start another activity and +receive a result back. To receive a result, call {@link android.app.Activity#startActivityForResult +startActivityForResult()} (instead of {@link android.app.Activity#startActivity +startActivity()}).</p> + +<p>For example, your app can start a camera app and receive the captured photo as a result. Or, you +might start the People app in order for the user to select a +contact and you'll receive the contact details as a result.</p> + +<p>Of course, the activity that responds must be designed to return a result. When it does, it +sends the result as another {@link android.content.Intent} object. Your activity receives it in +the {@link android.app.Activity#onActivityResult onActivityResult()} callback.</p> + +<p class="note"><strong>Note:</strong> You can use explicit or implicit intents when you call +{@link android.app.Activity#startActivityForResult startActivityForResult()}. When starting one of +your own activities to receive a result, you should use an explicit intent to ensure that you +receive the expected result.</p> + + +<h2 id="StartActivity">Start the Activity</h2> + +<p>There's nothing special about the {@link android.content.Intent} object you use when starting +an activity for a result, but you do need to pass an additional integer argument to the {@link +android.app.Activity#startActivityForResult startActivityForResult()} method.</p> + +<p>The integer argument is a "request code" that identifies your request. When you receive the +result {@link android.content.Intent}, the callback provides the same request code so that your +app can properly identify the result and determine how to handle it.</p> + +<p>For example, here's how to start an activity that allows the user to pick a contact:</p> + +<pre> +static final int PICK_CONTACT_REQUEST = 1; // The request code +... +private void pickContact() { + Intent pickContactIntent = new Intent(Intent.ACTION_PICK, new Uri("content://contacts")); + pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers + startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST); +} +</pre> + + +<h2 id="ReceiveResult">Receive the Result</h2> + +<p>When the user is done with the subsequent activity and returns, the system calls your activity's +{@link android.app.Activity#onActivityResult onActivityResult()} method. This method includes three +arguments:</p> + +<ul> + <li>The request code you passed to {@link +android.app.Activity#startActivityForResult startActivityForResult()}.</li> + <li>A result code specified by the second activity. This is either {@link +android.app.Activity#RESULT_OK} if the operation was successful or {@link +android.app.Activity#RESULT_CANCELED} if the user backed out or the operation failed for some +reason.</li> + <li>An {@link android.content.Intent} that carries the result data.</li> +</ul> + +<p>For example, here's how you can handle the result for the "pick a contact" intent:</p> + +<pre> +@Override +protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // Check which request we're responding to + if (requestCode == PICK_CONTACT_REQUEST) { + // Make sure the request was successful + if (resultCode == RESULT_OK) { + // The user picked a contact. + // The Intent's data Uri identifies which contact was selected. + + // Do something with the contact here (bigger example below) + } + } +} +</pre> + +<p>In this example, the result {@link android.content.Intent} returned by +Android's Contacts or People app provides a content {@link android.net.Uri} that identifies the +contact the user selected.</p> + +<p>In order to successfully handle the result, you must understand what the format of the result +{@link android.content.Intent} will be. Doing so is easy when the activity returning a result is +one of your own activities. Apps included with the Android platform offer their own APIs that +you can count on for specific result data. For instance, the People app (Contacts app on some older +versions) always returns a result with the content URI that identifies the selected contact, and the +Camera app returns a {@link android.graphics.Bitmap} in the {@code "data"} extra (see the class +about <a href="{@docRoot}training/camera/index.html">Capturing Photos</a>).</p> + + +<h4>Bonus: Read the contact data</h4> + +<p>The code above showing how to get a result from the People app doesn't go into +details about how to actually read the data from the result, because it requires more advanced +discussion about <a href="{@docRoot}guide/topics/providers/content-providers.html">content +providers</a>. However, if you're curious, here's some more code that shows how to query the +result data to get the phone number from the selected contact:</p> + +<pre> +@Override +protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // Check which request it is that we're responding to + if (requestCode == PICK_CONTACT_REQUEST) { + // Make sure the request was successful + if (resultCode == RESULT_OK) { + // Get the URI that points to the selected contact + Uri contactUri = data.getData(); + // We only need the NUMBER column, because there will be only one row in the result + String[] projection = {Phone.NUMBER}; + + // Perform the query on the contact to get the NUMBER column + // We don't need a selection or sort order (there's only one result for the given URI) + // CAUTION: The query() method should be called from a separate thread to avoid blocking + // your app's UI thread. (For simplicity of the sample, this code doesn't do that.) + // Consider using {@link android.content.CursorLoader} to perform the query. + Cursor cursor = getContentResolver() + .query(contactUri, projection, null, null, null); + cursor.moveToFirst(); + + // Retrieve the phone number from the NUMBER column + int column = cursor.getColumnIndex(Phone.NUMBER); + String number = cursor.getString(column); + + // Do something with the phone number... + } + } +} +</pre> + +<p class="note"><strong>Note:</strong> Before Android 2.3 (API level 9), performing a query +on the {@link android.provider.ContactsContract.Contacts Contacts Provider} (like the one shown +above) requires that your app declare the {@link +android.Manifest.permission#READ_CONTACTS} permission (see <a +href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>). However, +beginning with Android 2.3, the Contacts/People app grants your app a temporary +permission to read from the Contacts Provider when it returns you a result. The temporary permission +applies only to the specific contact requested, so you cannot query a contact other than the one +specified by the intent's {@link android.net.Uri}, unless you do declare the {@link +android.Manifest.permission#READ_CONTACTS} permission.</p> + + + + + + + + + + + + + + + diff --git a/docs/html/training/basics/intents/sending.jd b/docs/html/training/basics/intents/sending.jd new file mode 100644 index 0000000..a71c8f9 --- /dev/null +++ b/docs/html/training/basics/intents/sending.jd @@ -0,0 +1,211 @@ +page.title=Sending the User to Another App +parent.title=Interacting with Other Apps +parent.link=index.html + +trainingnavtop=true +next.title=Getting a Result from an Activity +next.link=result.html + +@jd:body + + +<div id="tb-wrapper"> + <div id="tb"> + +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#Build">Build an Implicit Intent</a></li> + <li><a href="#Verify">Verify There is an App to Receive the Intent</a></li> + <li><a href="#StartActivity">Start an Activity with the Intent</a></li> +</ol> + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li> +</ul> + + </div> +</div> + +<p>One of Android's most important features is an app's ability to send the user to another app +based on an "action" it would like to perform. For example, if +your app has the address of a business that you'd like to show on a map, you don't have to build +an activity in your app that shows a map. Instead, you can send a out a request to view the address +using an {@link android.content.Intent}. The Android system then starts an app that's able to view +the address on a map.</p> + +<p>As shown in the first class, <a href="{@docRoot}training/basics/firstapp/index.html">Building +Your First App</a>, you must use intents to navigate between activities in your own app. You +generally do so with an <em>explicit intent</em>, which defines the exact class name of the +component you want to start. However, when you want to have a separate app perform an action, such +as "view a map," you must use an <em>implicit intent</em>.</p> + +<p>This lesson shows you how to create an implicit intent for a particular action, and how to use it +to start an activity that performs the action in another app.</p> + + + +<h2 id="Build">Build an Implicit Intent</h2> + +<p>Implicit intents do not declare the class name of the component to start, but instead declare an +action to perform. The action specifies the thing you want to do, such as <em>view</em>, +<em>edit</em>, <em>send</em>, or <em>get</em> something. Intents often also include data associated +with the action, such as the address you want to view, or the email message you want to send. +Depending on the intent you want to create, the data might be a {@link android.net.Uri}, +one of several other data types, or the intent might not need data at all.</p> + +<p>If your data is a {@link android.net.Uri}, there's a simple {@link +android.content.Intent#Intent(String,Uri) Intent()} constructor you can use define the action and +data.</p> + +<p>For example, here's how to create an intent to initiate a phone call using the {@link +android.net.Uri} data to specify the telephone number:</p> + +<pre> +Uri number = Uri.parse("tel:5551234"); +Intent callIntent = new Intent(Intent.ACTION_DIAL, number); +</pre> + +<p>When your app invokes this intent by calling {@link android.app.Activity#startActivity +startActivity()}, the Phone app initiates a call to the given phone number.</p> + +<p>Here are a couple other intents and their action and {@link android.net.Uri} data +pairs:</p> + +<ul> + <li>View a map: +<pre> +// Map point based on address +Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"); +// Or map point based on latitude/longitude +// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level +Intent mapIntent = new Intent(Intent.ACTION_VIEW, location); +</pre> + </li> + <li>View a web page: +<pre> +Uri webpage = Uri.parse("http://www.android.com"); +Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage); +</pre> + </li> +</ul> + +<p>Other kinds of implicit intents require "extra" data that provide different data types, +such as a string. You can add one or more pieces of extra data using the various {@link +android.content.Intent#putExtra(String,String) putExtra()} methods.</p> + +<p>By default, the system determines the appropriate MIME type required by an intent based on the +{@link android.net.Uri} data that's included. If you don't include a {@link android.net.Uri} in the +intent, you should usually use {@link android.content.Intent#setType setType()} to specify the type +of data associated with the intent. Setting the MIME type further specifies which kinds of +activities should receive the intent.</p> + +<p>Here are some more intents that add extra data to specify the desired action:</p> + +<ul> + <li>Send an email with an attachment: +<pre> +Intent emailIntent = new Intent(Intent.ACTION_SEND); +// The intent does not have a URI, so declare the "text/plain" MIME type +emailIntent.setType(HTTP.PLAIN_TEXT_TYPE); +emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients +emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject"); +emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text"); +emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"); +// You can also attach multiple items by passing an ArrayList of Uris +</pre> + </li> + <li>Create a calendar event: +<pre> +Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI); +Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30); +Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30); +calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis()); +calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis()); +calendarIntent.putExtra(Events.TITLE, "Ninja class"); +calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo"); +</pre> +<p class="note"><strong>Note:</strong> This intent for a calendar event is supported only with API +level 14 and higher.</p> + </li> +</ul> + +<p class="note"><strong>Note:</strong> It's important that you define your {@link +android.content.Intent} to be as specific as possible. For example, if you want to display an image +using the {@link android.content.Intent#ACTION_VIEW} intent, you should specify a MIME type of +{@code image/*}. This prevents apps that can "view" other types of data (like a map app) from being +triggered by the intent.</p> + + + +<h2 id="Verify">Verify There is an App to Receive the Intent</h2> + +<p>Although the Android platform guarantees that certain intents will resolve to one of the +built-in apps (such as the Phone, Email, or Calendar app), you should always include a +verification step before invoking an intent.</p> + +<p class="caution"><strong>Caution:</strong> If you invoke an intent and there is no app +available on the device that can handle the intent, your app will crash.</p> + +<p>To verify there is an activity available that can respond to the intent, call {@link +android.content.pm.PackageManager#queryIntentActivities queryIntentActivities()} to get a list +of activities capable of handling your {@link android.content.Intent}. If the returned {@link +java.util.List} is not empty, you can safely use the intent. For example:</p> + +<pre> +PackageManager packageManager = {@link android.content.Context#getPackageManager()}; +List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0); +boolean isIntentSafe = activities.size() > 0; +</pre> + +<p>If <code>isIntentSafe</code> is <code>true</code>, then at least one app will respond to +the intent. If it is <code>false</code>, then there aren't any apps to handle the intent.</p> + +<p class="note"><strong>Note:</strong> You should perform this check when your activity first +starts in case you need to disable the feature that uses the intent before the user attempts to use +it. If you know of a specific app that can handle the intent, you can also provide a link for the +user to download the app (see how to <a +href="{@docRoot}guide/publishing/publishing.html#marketintent">link to an app on Google +Play</a>).</p> + + +<h2 id="StartActivity">Start an Activity with the Intent</h2> + +<div class="figure" style="width:200px"> + <img src="{@docRoot}images/training/basics/intents-choice.png" alt="" /> + <p class="img-caption"><strong>Figure 1.</strong> Example of the selection dialog that appears +when more than one app can handle an intent.</p> +</div> + +<p>Once you have created your {@link android.content.Intent} and set the extra info, call {@link +android.app.Activity#startActivity startActivity()} to send it to the system. If the system +identifies more than one activity that can handle the intent, it displays a dialog for the user to +select which app to use, as shown in figure 1. If there is only one activity that handles the +intent, the system immediately starts it.</p> + +<pre> +startActivity(intent); +</pre> + +<p>Here's a complete example that shows how to create an intent to view a map, verify that an +app exists to handle the intent, then start it:</p> + +<pre> +// Build the intent +Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"); +Intent mapIntent = new Intent(Intent.ACTION_VIEW, location); + +// Verify it resolves +PackageManager packageManager = {@link android.content.Context#getPackageManager()}; +List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0); +boolean isIntentSafe = activities.size() > 0; + +// Start an activity if it's safe +if (isIntentSafe) { + startActivity(mapIntent); +} +</pre> + + + + diff --git a/docs/html/training/basics/supporting-devices/index.jd b/docs/html/training/basics/supporting-devices/index.jd new file mode 100644 index 0000000..49ea81d --- /dev/null +++ b/docs/html/training/basics/supporting-devices/index.jd @@ -0,0 +1,49 @@ +page.title=Supporting Different Devices + +trainingnavtop=true +startpage=true +next.title=Supporting Multiple Languages +next.link=languages.html + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Dependencies and prerequisites</h2> +<ul> + <li>Android 1.6 or higher</li> +</ul> + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}guide/topics/resources/index.html">Application Resources</a></li> + <li><a href="{@docRoot}training/multiscreen/index.html">Designing for Multiple Screens</a></li> +</ul> + + +</div> +</div> + +<p>Android devices come in many shapes and sizes all around the world. With a wide range of device +types, you have an opportunity to reach a huge audience with your app. In order to be as successful +as possible on Android, your app needs to adapt to various device configurations. Some of the +important variations that you should consider include different languages, screen sizes, and +versions of the Android platform.</p> + +<p>This class teaches you how to use basic platform features that leverage alternative +resources and other features so your app can provide an optimized user experience on a +variety of Android-compatible devices, using a single application package (APK).</p> + +<h2>Lessons</h2> + +<dl> + <dt><b><a href="languages.html">Supporting Different Languages</a></b></dt> + <dd>Learn how to support multiple languages with alternative string resources.</dd> + <dt><b><a href="screens.html">Supporting Different Screens</a></b></dt> + <dd>Learn how to optimize the user experience for different screen sizes and densities.</dd> + <dt><b><a href="platforms.html">Supporting Different Platform Versions</a></b></dt> + <dd>Learn how to use APIs available in new versions of Android while continuing to support +older versions of Android.</dd> +</dl> + diff --git a/docs/html/training/basics/supporting-devices/languages.jd b/docs/html/training/basics/supporting-devices/languages.jd new file mode 100644 index 0000000..fcc95c2 --- /dev/null +++ b/docs/html/training/basics/supporting-devices/languages.jd @@ -0,0 +1,134 @@ +page.title=Supporting Different Languages +parent.title=Supporting Different Devices +parent.link=index.html + +trainingnavtop=true +next.title=Supporting Different Screens +next.link=screens.html + +@jd:body + + +<div id="tb-wrapper"> + <div id="tb"> + <h2>This class teaches you to</h2> + <ol> + <li><a href="#CreateDirs">Create Locale Directories and String Files</a></li> + <li><a href="#UseString">Use the String Resources</a></li> + </ol> + <h2>You should also read</h2> + <ul> + <li><a href="{@docRoot}guide/topics/resources/localization.html">Localization</a></li> + </ul> + </div> +</div> + +<p>It’s always a good practice to extract UI strings from your app code and keep them +in an external file. Android makes this easy with a resources directory in each Android +project.</p> + +<p>If you created your project using the Android SDK +Tools (read <a href="{@docRoot}training/basics/firstapp/creating-project.html">Creating an +Android Project</a>), the tools create a <code>res/</code> directory in the top level of +the project. Within this <code>res/</code> directory are subdirectories for various resource +types. There are also a few default files such as <code>res/values/strings.xml</code>, which holds +your string values.</p> + + +<h2 id="CreateDirs">Create Locale Directories and String Files</h2> + +<p>To add support for more languages, create additional <code>values</code> directories inside +<code>res/</code> that include a hyphen and the ISO country code at the end of the +directory name. For example, <code>values-es/</code> is the directory containing simple +resourcess for the Locales with the language code "es". Android loads the appropriate resources +according to the locale settings of the device at run time.</p> + +<p>Once you’ve decided on the languages you will support, create the resource subdirectories and +string resource files. For example:</p> + +<pre class="classic no-pretty-print"> +MyProject/ + res/ + values/ + strings.xml + values-es/ + strings.xml + values-fr/ + strings.xml +</pre> + +<p>Add the string values for each locale into the appropriate file.</p> + +<p>At runtime, the Android system uses the appropriate set of string resources based on the +locale currently set for the user's device.</p> + +<p>For example, the following are some different string resource files for different languages.</p> + + +<p>English (default locale), <code>/values/strings.xml</code>:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title">My Application</string> + <string name="hello_world">Hello World!</string> +</resources> +</pre> + + +<p>Spanish, <code>/values-es/strings.xml</code>:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title">Mi Aplicación</string> + <string name="hello_world">Hola Mundo!</string> +</resources> +</pre> + + +<p>French, <code>/values-fr/strings.xml</code>:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="title">Ma Application</string> + <string name="hello_world">Bonjour tout le Monde!</string> +</resources> +</pre> + + +<h2 id="UseString">Use the String Resources</h2> + +<p>You can reference your string resources in your source code and other XML files using the +resource name defined by the {@code <string>} element's {@code name} attribute.</p> + +<p>In your source code, you can refer to a string resource with the syntax {@code +R.string.<string_name>}. There are a variety of methods that accept a string resource this +way.</p> + +<p>For example:</p> + +<pre> +// Get a string resource from your app's {@link android.content.res.Resources} +String hello = {@link android.content.Context#getResources()}.getString(R.string.hello_world); + +// Or supply a string resource to a method that requires a string +TextView textView = new TextView(this); +textView.setText(R.string.hello_world); +</pre> + +<p>In other XML files, you can refer to a string resource with the syntax {@code +@string/<string_name>} whenever the XML attribute accepts a string value.</p> + +<p>For example:</p> + +<pre> +<TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/hello_world" /> +</pre> + + + diff --git a/docs/html/training/basics/supporting-devices/platforms.jd b/docs/html/training/basics/supporting-devices/platforms.jd new file mode 100644 index 0000000..0d4e7d9 --- /dev/null +++ b/docs/html/training/basics/supporting-devices/platforms.jd @@ -0,0 +1,138 @@ +page.title=Supporting Different Platform Versions +parent.title=Supporting Different Devices +parent.link=index.html + +trainingnavtop=true +previous.title=Supporting Different Screens +previous.link=screens.html + +@jd:body + + +<div id="tb-wrapper"> + <div id="tb"> + + <h2>This lesson teaches you to</h2> + <ol> + <li><a href="#sdk-versions">Specify Minimum and Target API Levels</a></li> + <li><a href="#version-codes">Check System Version at Runtime</a></li> + <li><a href="#style-themes">Use Platform Styles and Themes</a></li> + </ol> + + <h2>You should also read</h2> + <ul> + <li><a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a></li> + <li><a +href="{@docRoot}sdk/compatibility-library.html">Android Support Library</a></li> + </ul> + </div> +</div> + +<p>While the latest versions of Android often provide great APIs for your app, you should continue +to support older versions of Android until more devices get updated. This +lesson shows you how to take advantage of the latest APIs while continuing to support older +versions as well.</p> + +<p>The dashboard for <a +href="http://developer.android.com/resources/dashboard/platform-versions.html">Platform Versions</a> +is updated regularly to show the distribution of active +devices running each version of Android, based on the number of devices that visit the Google Play +Store. Generally, it’s a good practice to support about 90% of the active devices, while +targeting your app to the latest version.</p> + +<p class="note"><strong>Tip:</strong> In order to provide the best features and +functionality across several Android versions, you should use the <a +href="{@docRoot}sdk/compatibility-library.html">Android Support Library</a> in your app, +which allows you to use several recent platform APIs on older versions.</p> + + + +<h2 id="sdk-versions">Specify Minimum and Target API Levels</h2> + +<p>The <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a> file +describes details about your app and +identifies which versions of Android it supports. Specifically, the <code>minSdkVersion</code> +and <code>targetSdkVersion</code> attributes for the <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk}</a> element +identify the lowest API level with which your app is compatible and the highest API level against +which you’ve designed and tested your app.</p> + +<p>For example:</p> + +<pre> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" ... > + <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15" /> + ... +</manifest> +</pre> + +<p>As new versions of Android are released, some style and behaviors may change. +To allow your app to take advantage of these changes and ensure that your app fits the style of +each user's device, you should set the +<a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> +value to match the latest Android version +available.</p> + + + +<h2 id="version-codes">Check System Version at Runtime</h2> + +<p>Android provides a unique code for each platform version in the {@link android.os.Build} +constants class. Use these codes within your app to build conditions that ensure the code that +depends on higher API levels is executed only when those APIs are available on the system.</p> + +<pre> +private void setUpActionBar() { + // Make sure we're running on Honeycomb or higher to use ActionBar APIs + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + ActionBar actionBar = getActionBar(); + actionBar.setDisplayHomeAsUpEnabled(true); + } +} +</pre> + + + +<p class="note"><strong>Note:</strong> When parsing XML resources, Android ignores XML +attributes that aren’t supported by the current device. So you can safely use XML attributes that +are only supported by newer versions without worrying about older versions breaking when they +encounter that code. For example, if you set the +<code>targetSdkVersion="11"</code>, your app includes the {@link android.app.ActionBar} by default +on Android 3.0 and higher. To then add menu items to the action bar, you need to set +<code>android:showAsAction="ifRoom"</code> in your menu resource XML. It's safe to do this +in a cross-version XML file, because the older versions of Android simply ignore the +<code>showAsAction</code> attribute (that is, you <em>do not</em> need a separate +version in <code>res/menu-v11/</code>).</p> + + + +<h2 id="style-themes">Use Platform Styles and Themes</h2> + +<p>Android provides user experience themes that give apps the look and feel of the +underlying operating system. These themes can be applied to your app within the +manifest file. By using these built in styles and themes, your app will +naturally follow the latest look and feel of Android with each new release.</p> + +<p>To make your activity look like a dialog box:</p> + +<pre><activity android:theme="@android:style/Theme.Dialog"></pre> + +<p>To make your activity have a transparent background:</p> + +<pre><activity android:theme="@android:style/Theme.Translucent"></pre> + +<p>To apply your own custom theme defined in <code>/res/values/styles.xml</code>:</p> + +<pre><activity android:theme="@style/CustomTheme"></pre> + +<p>To apply a theme to your entire app (all activities), add the <code>android:theme</code> +attribute +to the <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code +<application>}</a> element:</p> + +<pre><application android:theme="@style/CustomTheme"></pre> + +<p>For more about creating and using themes, read the <a +href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a> guide.</p> + diff --git a/docs/html/training/basics/supporting-devices/screens.jd b/docs/html/training/basics/supporting-devices/screens.jd new file mode 100644 index 0000000..8697cd5 --- /dev/null +++ b/docs/html/training/basics/supporting-devices/screens.jd @@ -0,0 +1,180 @@ +page.title=Supporting Different Screens +parent.title=Supporting Different Devices +parent.link=index.html + +trainingnavtop=true +previous.title=Supporting Different Languages +previous.link=languages.html +next.title=Supporting Different Platform Versions +next.link=platforms.html + +@jd:body + +<div id="tb-wrapper"> + <div id="tb"> + + <h2>This lesson teaches you to</h2> + <ol> + <li><a href="#create-layouts">Create Different Layouts</a></li> + <li><a href="#create-bitmaps">Create Different Bitmaps</a></li> + </ol> + + <h2>You should also read</h2> + <ul> + <li><a href="{@docRoot}training/multiscreen/index.html">Designing for Multiple +Screens</a></li> + <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple +Screens</a></li> + <li><a href="{@docRoot}design/style/iconography.html">Iconography design guide</a></li> + </ul> + </div> +</div> + +<p>Android categorizes device screens using two general properties: size and density. You should +expect that your app will be installed on devices with screens that range in both size +and density. As such, you should include some alternative resources that optimize your app’s +appearance for different screen sizes and densities.</p> + +<ul> + <li>There are four generalized sizes: small, normal, large, xlarge</li> + <li>And four generalized densities: low (ldpi), medium (mdpi), high (hdpi), extra high +(xhdpi)</li> +</ul> + +<p>To declare different layouts and bitmaps you'd like to use for different screens, you must place +these alternative resources in separate directories, similar to how you do for different language +strings.</p> + +<p>Also be aware that the screens orientation (landscape or portrait) is considered a variation of +screen size, so many apps should revise the layout to optimize the user experience in each +orientation.</p> + + +<h2 id="create-layouts">Create Different Layouts</h2> + +<p>To optimize your user experience on different screen sizes, you should create a unique layout XML +file for each screen size you want to support. Each layout should be +saved into the appropriate resources directory, named with a <code>-<screen_size></code> +suffix. For example, a unique layout for large screens should be saved under +<code>res/layout-large/</code>.</p> + +<p class="note"><strong>Note:</strong> Android automatically scales your layout in order to +properly fit the screen. Thus, your layouts for different screen sizes don't +need to worry about the absolute size of UI elements but instead focus on the layout structure that +affects the user experience (such as the size or position of important views relative to sibling +views).</p> + +<p>For example, this project includes a default layout and an alternative layout for <em>large</em> +screens:</p> + +<pre class="classic no-pretty-print"> +MyProject/ + res/ + layout/ + main.xml + layout-large/ + main.xml +</pre> + +<p>The file names must be exactly the same, but their contents are different in order to provide +an optimized UI for the corresponding screen size.</p> + +<p>Simply reference the layout file in your app as usual:</p> + +<pre> +@Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); +} +</pre> + +<p>The system loads the layout file from the appropriate layout directory based on screen size of +the device on which your app is running. More information about how Android selects the +appropriate resource is available in the <a +href="{@docRoot}guide/topics/resources/providing-resources.html#BestMatch">Providing Resources</a> +guide.</p> + +<p>As another example, here's a project with an alternative layout for landscape orientation:</p> + +<pre class="classic no-pretty-print"> +MyProject/ + res/ + layout/ + main.xml + layout-land/ + main.xml +</pre> + +<p>By default, the <code>layout/main.xml</code> file is used for portrait orientation.</p> + +<p>If you want a provide a special layout for landscape, including while on large screens, then +you need to use both the <code>large</code> and <code>land</code> qualifier:</p> + +<pre class="classic no-pretty-print"> +MyProject/ + res/ + layout/ # default (portrait) + main.xml + layout-land/ # landscape + main.xml + layout-large/ # large (portrait) + main.xml + layout-large-land/ # large landscape + main.xml +</pre> + +<p class="note"><strong>Note:</strong> Android 3.2 and above supports an advanced method of +defining screen sizes that allows you to specify resources for screen sizes based on +the minimum width and height in terms of density-independent pixels. This lesson does not cover +this new technique. For more information, read <a +href="{@docRoot}training/multiscreen/index.html">Designing for Multiple +Screens</a>.</p> + + + +<h2 id="create-bitmaps">Create Different Bitmaps</h2> + +<p>You should always provide bitmap resources that are properly scaled to each of the generalized +density buckets: low, medium, high and extra-high density. This helps you achieve good graphical +quality and performance on all screen densities.</p> + +<p>To generate these images, you should start with your raw resource in vector format and generate +the images for each density using the following size scale:</p> +<ul> +<li>xhdpi: 2.0</li> +<li>hdpi: 1.5</li> +<li>mdpi: 1.0 (baseline)</li> +<li>ldpi: 0.75</li> +</ul> + +<p>This means that if you generate a 200x200 image for xhdpi devices, you should generate the same +resource in 150x150 for hdpi, 100x100 for mdpi, and 75x75 for ldpi devices.</p> + +<p>Then, place the files in the appropriate drawable resource directory:</p> + +<pre class="classic no-pretty-print"> +MyProject/ + res/ + drawable-xhdpi/ + awesomeimage.png + drawable-hdpi/ + awesomeimage.png + drawable-mdpi/ + awesomeimage.png + drawable-ldpi/ + awesomeimage.png +</pre> + +<p>Any time you reference <code>@drawable/awesomeimage</code>, the system selects the +appropriate bitmap based on the screen's density.</p> + +<p class="note"><strong>Note:</strong> Low-density (ldpi) resources aren’t always necessary. When +you provide hdpi assets, the system scales them down by one half to properly fit ldpi +screens.</p> + +<p>For more tips and guidelines about creating icon assets for your app, see the +<a href="{@docRoot}design/style/iconography.html">Iconography design guide</a>.</p> + + + diff --git a/docs/html/training/tv/optimizing-layouts-tv.jd b/docs/html/training/tv/optimizing-layouts-tv.jd index 6eac6d3..e4a8e69 100644 --- a/docs/html/training/tv/optimizing-layouts-tv.jd +++ b/docs/html/training/tv/optimizing-layouts-tv.jd @@ -16,7 +16,7 @@ next.link=optimizing-navigation-tv.html <li><a href="#DesignLandscapeLayouts">Design Landscape Layouts</a></li> <li><a href="#MakeTextControlsEasyToSee">Make Text and Controls Easy to See</a></li> <li><a href="#DesignForLargeScreens">Design for High-Density Large Screens</a></li> - <li><a href="#HandleLargeBitmaps">Handle Large Bitmaps in Your Application</a></li> + <li><a href="#HandleLargeBitmaps">Design to Handle Large Bitmaps</a></li> </ol> <h2>You should also read</h2> diff --git a/docs/html/training/tv/optimizing-navigation-tv.jd b/docs/html/training/tv/optimizing-navigation-tv.jd index 8b5878e..bb78258 100644 --- a/docs/html/training/tv/optimizing-navigation-tv.jd +++ b/docs/html/training/tv/optimizing-navigation-tv.jd @@ -5,7 +5,7 @@ parent.link=index.html trainingnavtop=true previous.title=Optimizing Layouts for TV previous.link=optimizing-layouts-tv.html -next.title=Handling features not supported on TV +next.title=Handling Features Not Supported on TV next.link=unsupported-features-tv.html @jd:body diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java index 7269a71..b3a8fd7 100644 --- a/graphics/java/android/graphics/ImageFormat.java +++ b/graphics/java/android/graphics/ImageFormat.java @@ -25,34 +25,38 @@ public class ImageFormat { public static final int UNKNOWN = 0; /** - * RGB format used for pictures encoded as RGB_565 see + * RGB format used for pictures encoded as RGB_565. See * {@link android.hardware.Camera.Parameters#setPictureFormat(int)}. */ public static final int RGB_565 = 4; /** - * Android YUV format: + * <p>Android YUV format.</p> * - * This format is exposed to software decoders and applications. + * <p>This format is exposed to software decoders and applications.</p> * - * YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed - * by (W/2) x (H/2) Cr and Cb planes. + * <p>YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed + * by (W/2) x (H/2) Cr and Cb planes.</p> * - * This format assumes - * - an even width - * - an even height - * - a horizontal stride multiple of 16 pixels - * - a vertical stride equal to the height + * <p>This format assumes + * <ul> + * <li>an even width</li> + * <li>an even height</li> + * <li>a horizontal stride multiple of 16 pixels</li> + * <li>a vertical stride equal to the height</li> + * </ul> + * </p> * - * y_size = stride * height - * c_size = ALIGN(stride/2, 16) * height/2 - * size = y_size + c_size * 2 - * cr_offset = y_size - * cb_offset = y_size + c_size + * <pre> y_size = stride * height + * c_size = ALIGN(stride/2, 16) * height/2 + * size = y_size + c_size * 2 + * cr_offset = y_size + * cb_offset = y_size + c_size</pre> * - * Whether this format is supported by the camera hardware can be determined - * by + * This format is guaranteed to be supported for camera preview images since + * API level 12; for earlier API versions, check * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}. + * </p> */ public static final int YV12 = 0x32315659; diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index c97785e..8cb8466 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -21,6 +21,8 @@ import android.text.SpannableString; import android.text.SpannedString; import android.text.TextUtils; +import java.util.Locale; + /** * The Paint class holds the style and color information about how to draw * geometries, text and bitmaps. @@ -44,6 +46,8 @@ public class Paint { private float mCompatScaling; private float mInvCompatScaling; + private Locale mLocale; + /** * @hide */ @@ -348,6 +352,7 @@ public class Paint { // setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV // ? HINTING_OFF : HINTING_ON); mCompatScaling = mInvCompatScaling = 1; + mLocale = Locale.getDefault(); } /** @@ -360,6 +365,7 @@ public class Paint { public Paint(Paint paint) { mNativePaint = native_initWithPaint(paint.mNativePaint); setClassVariablesFrom(paint); + mLocale = paint.mLocale; } /** Restores the paint to its default settings. */ @@ -373,6 +379,7 @@ public class Paint { mHasCompatScaling = false; mCompatScaling = mInvCompatScaling = 1; mBidiFlags = BIDI_DEFAULT_LTR; + mLocale = Locale.getDefault(); } /** @@ -412,6 +419,7 @@ public class Paint { shadowColor = paint.shadowColor; mBidiFlags = paint.mBidiFlags; + mLocale = paint.mLocale; } /** @hide */ @@ -1045,6 +1053,36 @@ public class Paint { } /** + * Get the text Locale. + * + * @return the paint's Locale used for drawing text, never null. + */ + public Locale getTextLocale() { + return mLocale; + } + + /** + * Set the text locale. + * + * This controls how the text will be drawn. Providing the ROOT Locale (default case) + * means that the text will be drawn with the font corresponding to its script. + * + * Using the CHINESE or CHINA Locale means that the text will be drawn with a Chinese font. + * Using the JAPANESE or JAPAN Locale means that the text will be drawn with a Japanese font. + * Using the KOREAN or KOREA Locale means that the text will be drawn with a Korean font. + * + * @param locale the paint's locale value for drawing text, must not be null. + */ + public void setTextLocale(Locale locale) { + if (locale == null) { + throw new IllegalArgumentException("locale cannot be null"); + } + if (locale.equals(mLocale)) return; + mLocale = locale; + native_setTextLocale(mNativePaint, locale.toString()); + } + + /** * Return the paint's text size. * * @return the paint's text size. @@ -2144,6 +2182,9 @@ public class Paint { private static native void native_setTextAlign(int native_object, int align); + private static native void native_setTextLocale(int native_object, + String locale); + private static native int native_getTextWidths(int native_object, char[] text, int index, int count, float[] widths); private static native int native_getTextWidths(int native_object, diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java index cd5300d..10ccb87 100644 --- a/graphics/java/android/renderscript/Allocation.java +++ b/graphics/java/android/renderscript/Allocation.java @@ -136,7 +136,6 @@ public class Allocation extends BaseObj { * consumer. This usage will cause the allocation to be created * read only. * - * @hide */ public static final int USAGE_IO_INPUT = 0x0020; @@ -145,7 +144,6 @@ public class Allocation extends BaseObj { * SurfaceTexture producer. The dimensions and format of the * SurfaceTexture will be forced to those of the allocation. * - * @hide */ public static final int USAGE_IO_OUTPUT = 0x0040; @@ -193,8 +191,8 @@ public class Allocation extends BaseObj { /** * Get the element of the type of the Allocation. * - * @hide - * @return Element + * @return Element that describes the structure of data in the + * allocation * */ public Element getElement() { @@ -204,8 +202,8 @@ public class Allocation extends BaseObj { /** * Get the usage flags of the Allocation. * - * @hide - * @return usage + * @return usage flags associated with the allocation. e.g. + * script, texture, etc. * */ public int getUsage() { @@ -215,12 +213,11 @@ public class Allocation extends BaseObj { /** * Get the size of the Allocation in bytes. * - * @hide - * @return sizeInBytes + * @return size of the Allocation in bytes. * */ - public int getSizeBytes() { - return mType.getCount() * mType.getElement().getSizeBytes(); + public int getBytesSize() { + return mType.getCount() * mType.getElement().getBytesSize(); } private void updateCacheInfo(Type t) { @@ -362,8 +359,6 @@ public class Allocation extends BaseObj { * Send a buffer to the output stream. The contents of the * Allocation will be undefined after this operation. * - * @hide - * */ public void ioSend() { if ((mUsage & USAGE_IO_OUTPUT) == 0) { @@ -385,8 +380,6 @@ public class Allocation extends BaseObj { /** * Receive the latest input into the Allocation. * - * @hide - * */ public void ioReceive() { if ((mUsage & USAGE_IO_INPUT) == 0) { @@ -424,37 +417,37 @@ public class Allocation extends BaseObj { throw new RSIllegalArgumentException("Allocation kind is " + mType.getElement().mKind + ", type " + mType.getElement().mType + - " of " + mType.getElement().getSizeBytes() + + " of " + mType.getElement().getBytesSize() + " bytes, passed bitmap was " + bc); } break; case ARGB_8888: if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || - (mType.getElement().getSizeBytes() != 4)) { + (mType.getElement().getBytesSize() != 4)) { throw new RSIllegalArgumentException("Allocation kind is " + mType.getElement().mKind + ", type " + mType.getElement().mType + - " of " + mType.getElement().getSizeBytes() + + " of " + mType.getElement().getBytesSize() + " bytes, passed bitmap was " + bc); } break; case RGB_565: if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) || - (mType.getElement().getSizeBytes() != 2)) { + (mType.getElement().getBytesSize() != 2)) { throw new RSIllegalArgumentException("Allocation kind is " + mType.getElement().mKind + ", type " + mType.getElement().mType + - " of " + mType.getElement().getSizeBytes() + + " of " + mType.getElement().getBytesSize() + " bytes, passed bitmap was " + bc); } break; case ARGB_4444: if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || - (mType.getElement().getSizeBytes() != 2)) { + (mType.getElement().getBytesSize() != 2)) { throw new RSIllegalArgumentException("Allocation kind is " + mType.getElement().mKind + ", type " + mType.getElement().mType + - " of " + mType.getElement().getSizeBytes() + + " of " + mType.getElement().getBytesSize() + " bytes, passed bitmap was " + bc); } break; @@ -583,7 +576,7 @@ public class Allocation extends BaseObj { */ public void setFromFieldPacker(int xoff, FieldPacker fp) { mRS.validate(); - int eSize = mType.mElement.getSizeBytes(); + int eSize = mType.mElement.getBytesSize(); final byte[] data = fp.getData(); int count = data.length / eSize; @@ -612,7 +605,7 @@ public class Allocation extends BaseObj { } final byte[] data = fp.getData(); - int eSize = mType.mElement.mElements[component_number].getSizeBytes(); + int eSize = mType.mElement.mElements[component_number].getBytesSize(); eSize *= mType.mElement.mArraySizes[component_number]; if (data.length != eSize) { @@ -665,7 +658,7 @@ public class Allocation extends BaseObj { * @param d the source data array */ public void copy1DRangeFromUnchecked(int off, int count, int[] d) { - int dataSize = mType.mElement.getSizeBytes() * count; + int dataSize = mType.mElement.getBytesSize() * count; data1DChecks(off, count, d.length * 4, dataSize); mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize); } @@ -679,7 +672,7 @@ public class Allocation extends BaseObj { * @param d the source data array */ public void copy1DRangeFromUnchecked(int off, int count, short[] d) { - int dataSize = mType.mElement.getSizeBytes() * count; + int dataSize = mType.mElement.getBytesSize() * count; data1DChecks(off, count, d.length * 2, dataSize); mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize); } @@ -693,7 +686,7 @@ public class Allocation extends BaseObj { * @param d the source data array */ public void copy1DRangeFromUnchecked(int off, int count, byte[] d) { - int dataSize = mType.mElement.getSizeBytes() * count; + int dataSize = mType.mElement.getBytesSize() * count; data1DChecks(off, count, d.length, dataSize); mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize); } @@ -707,7 +700,7 @@ public class Allocation extends BaseObj { * @param d the source data array */ public void copy1DRangeFromUnchecked(int off, int count, float[] d) { - int dataSize = mType.mElement.getSizeBytes() * count; + int dataSize = mType.mElement.getBytesSize() * count; data1DChecks(off, count, d.length * 4, dataSize); mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize); } @@ -1030,30 +1023,6 @@ public class Allocation extends BaseObj { } /** - * @hide - * This API is hidden and only intended to be used for - * transitional purposes. - * - * @param type renderscript type describing data layout - * @param mips specifies desired mipmap behaviour for the - * allocation - * @param usage bit field specifying how the allocation is - * utilized - */ - static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, - int usage, int pointer) { - rs.validate(); - if (type.getID(rs) == 0) { - throw new RSInvalidStateException("Bad Type"); - } - int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, pointer); - if (id == 0) { - throw new RSRuntimeException("Allocation creation failed."); - } - return new Allocation(id, rs, type, usage); - } - - /** * Creates a renderscript allocation with the size specified by * the type and no mipmaps generated by default * @@ -1194,8 +1163,11 @@ public class Allocation extends BaseObj { } /** + * For allocations used with io operations, returns the handle + * onto a raw buffer that is being managed by the screen + * compositor. * - * @hide + * @return Surface object associated with allocation * */ public Surface getSurface() { @@ -1203,7 +1175,9 @@ public class Allocation extends BaseObj { } /** - * @hide + * Associate a surface for io output with this allocation + * + * @param sur Surface to associate with allocation */ public void setSurface(Surface sur) { mRS.validate(); diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java index d75c951..28914ce 100644 --- a/graphics/java/android/renderscript/Element.java +++ b/graphics/java/android/renderscript/Element.java @@ -85,13 +85,13 @@ public class Element extends BaseObj { } /** - * @hide * @return element size in bytes */ - public int getSizeBytes() {return mSize;} + public int getBytesSize() {return mSize;} /** - * @hide + * Returns the number of vector components. 2 for float2, 4 for + * float4, etc. * @return element vector size */ public int getVectorSize() {return mVectorSize;} @@ -114,10 +114,6 @@ public class Element extends BaseObj { * RS_* objects. 32 bit opaque handles. */ public enum DataType { - /** - * @hide - * new enum - */ NONE (0, 0), //FLOAT_16 (1, 2), FLOAT_32 (2, 4), @@ -150,7 +146,8 @@ public class Element extends BaseObj { RS_PROGRAM_FRAGMENT (1006, 4), RS_PROGRAM_VERTEX (1007, 4), RS_PROGRAM_RASTER (1008, 4), - RS_PROGRAM_STORE (1009, 4); + RS_PROGRAM_STORE (1009, 4), + RS_FONT (1010, 4); int mID; int mSize; @@ -201,7 +198,10 @@ public class Element extends BaseObj { } /** - * @hide + * Elements could be simple, such as an int or a float, or a + * structure with multiple sub elements, such as a collection of + * floats, float2, float4. This function returns zero for simple + * elements or the number of sub-elements otherwise. * @return number of sub-elements in this element */ public int getSubElementCount() { @@ -212,7 +212,8 @@ public class Element extends BaseObj { } /** - * @hide + * For complex elements, this function will return the + * sub-element at index * @param index index of the sub-element to return * @return sub-element in this element at given index */ @@ -227,7 +228,8 @@ public class Element extends BaseObj { } /** - * @hide + * For complex elements, this function will return the + * sub-element name at index * @param index index of the sub-element * @return sub-element in this element at given index */ @@ -242,7 +244,9 @@ public class Element extends BaseObj { } /** - * @hide + * For complex elements, some sub-elements could be statically + * sized arrays. This function will return the array size for + * sub-element at index * @param index index of the sub-element * @return array size of sub-element in this element at given index */ @@ -257,7 +261,8 @@ public class Element extends BaseObj { } /** - * @hide + * This function specifies the location of a sub-element within + * the element * @param index index of the sub-element * @return offset in bytes of sub-element in this element at given index */ @@ -272,7 +277,6 @@ public class Element extends BaseObj { } /** - * @hide * @return element data type */ public DataType getDataType() { @@ -280,7 +284,6 @@ public class Element extends BaseObj { } /** - * @hide * @return element data kind */ public DataKind getDataKind() { @@ -455,6 +458,13 @@ public class Element extends BaseObj { return rs.mElement_PROGRAM_STORE; } + public static Element FONT(RenderScript rs) { + if(rs.mElement_FONT == null) { + rs.mElement_FONT = createUser(rs, DataType.RS_FONT); + } + return rs.mElement_FONT; + } + public static Element A_8(RenderScript rs) { if(rs.mElement_A_8 == null) { diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java index 104d1cd..d9f64c6 100644 --- a/graphics/java/android/renderscript/Program.java +++ b/graphics/java/android/renderscript/Program.java @@ -78,14 +78,20 @@ public class Program extends BaseObj { } /** - * @hide + * Program object can have zero or more constant allocations + * associated with it. This method returns the total count. + * @return number of constant input types */ public int getConstantCount() { return mConstants != null ? mConstants.length : 0; } /** - * @hide + * Returns the type of the constant buffer used in the program + * object. It could be used to query internal elements or create + * an allocation to store constant data. + * @param slot index of the constant input type to return + * @return constant input type */ public Type getConstant(int slot) { if (slot < 0 || slot >= mConstants.length) { @@ -95,14 +101,17 @@ public class Program extends BaseObj { } /** - * @hide + * Returns the number of textures used in this program object + * @return number of texture inputs */ public int getTextureCount() { return mTextureCount; } /** - * @hide + * Returns the type of texture at a given slot. e.g. 2D or Cube + * @param slot index of the texture input + * @return texture input type */ public TextureType getTextureType(int slot) { if ((slot < 0) || (slot >= mTextureCount)) { @@ -112,7 +121,10 @@ public class Program extends BaseObj { } /** - * @hide + * Returns the name of the texture input at a given slot. e.g. + * tex0, diffuse, spec + * @param slot index of the texture input + * @return texture input name */ public String getTextureName(int slot) { if ((slot < 0) || (slot >= mTextureCount)) { @@ -318,7 +330,6 @@ public class Program extends BaseObj { } /** - * @hide * Adds a texture input to the Program * * @param texType describes that the texture to append it (2D, diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/graphics/java/android/renderscript/ProgramRaster.java index 93ee0ce..e40751f 100644 --- a/graphics/java/android/renderscript/ProgramRaster.java +++ b/graphics/java/android/renderscript/ProgramRaster.java @@ -48,15 +48,16 @@ public class ProgramRaster extends BaseObj { } /** - * @hide + * Specifies whether vertices are rendered as screen aligned + * elements of a specified size * @return whether point sprites are enabled */ - public boolean getPointSpriteEnabled() { + public boolean isPointSpriteEnabled() { return mPointSprite; } /** - * @hide + * Specifies how triangles are culled based on their orientation * @return cull mode */ public CullMode getCullMode() { diff --git a/graphics/java/android/renderscript/ProgramStore.java b/graphics/java/android/renderscript/ProgramStore.java index 677dadd..d0fd6e5 100644 --- a/graphics/java/android/renderscript/ProgramStore.java +++ b/graphics/java/android/renderscript/ProgramStore.java @@ -150,7 +150,8 @@ public class ProgramStore extends BaseObj { } /** - * @hide + * Returns the function used to test writing into the depth + * buffer * @return depth function */ public DepthFunc getDepthFunc() { @@ -158,47 +159,47 @@ public class ProgramStore extends BaseObj { } /** - * @hide - * @return whether depth writes are enabled + * Queries whether writes are enabled into the depth buffer + * @return depth mask */ - public boolean getDepthMaskEnabled() { + public boolean isDepthMaskEnabled() { return mDepthMask; } /** - * @hide + * Queries whether red channel is written * @return red color channel mask */ - public boolean getColorMaskREnabled() { + public boolean isColorMaskRedEnabled() { return mColorMaskR; } /** - * @hide + * Queries whether green channel is written * @return green color channel mask */ - public boolean getColorMaskGEnabled() { + public boolean isColorMaskGreenEnabled() { return mColorMaskG; } /** - * @hide + * Queries whether blue channel is written * @return blue color channel mask */ - public boolean getColorMaskBEnabled() { + public boolean isColorMaskBlueEnabled() { return mColorMaskB; } /** - * @hide + * Queries whether alpha channel is written * @return alpha channel mask */ - public boolean getColorMaskAEnabled() { + public boolean isColorMaskAlphaEnabled() { return mColorMaskA; } /** - * @hide + * Specifies how the source blending factor is computed * @return source blend function */ public BlendSrcFunc getBlendSrcFunc() { @@ -206,7 +207,7 @@ public class ProgramStore extends BaseObj { } /** - * @hide + * Specifies how the destination blending factor is computed * @return destination blend function */ public BlendDstFunc getBlendDstFunc() { @@ -214,10 +215,11 @@ public class ProgramStore extends BaseObj { } /** - * @hide + * Specifies whether colors are dithered before writing into the + * framebuffer * @return whether dither is enabled */ - public boolean getDitherEnabled() { + public boolean isDitherEnabled() { return mDither; } diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java index 32c908e..74d666b 100644 --- a/graphics/java/android/renderscript/ProgramVertex.java +++ b/graphics/java/android/renderscript/ProgramVertex.java @@ -55,14 +55,15 @@ public class ProgramVertex extends Program { } /** - * @hide + * @return number of input attribute elements */ public int getInputCount() { return mInputs != null ? mInputs.length : 0; } /** - * @hide + * @param slot location of the input to return + * @return input attribute element */ public Element getInput(int slot) { if (slot < 0 || slot >= mInputs.length) { diff --git a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java index fac4c3d..54f21b8 100644 --- a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java +++ b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java @@ -204,7 +204,7 @@ public class ProgramVertexFixedFunction extends ProgramVertex { public Constants(RenderScript rs) { Type constInputType = ProgramVertexFixedFunction.Builder.getConstantInputType(rs); mAlloc = Allocation.createTyped(rs, constInputType); - int bufferSize = constInputType.getElement().getSizeBytes()* + int bufferSize = constInputType.getElement().getBytesSize()* constInputType.getCount(); mIOBuffer = new FieldPacker(bufferSize); mModel = new Matrix4f(); diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java index 03294b5..abbcdd9 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -664,6 +664,7 @@ public class RenderScript { Element mElement_PROGRAM_VERTEX; Element mElement_PROGRAM_RASTER; Element mElement_PROGRAM_STORE; + Element mElement_FONT; Element mElement_A_8; Element mElement_RGB_565; diff --git a/graphics/java/android/renderscript/Sampler.java b/graphics/java/android/renderscript/Sampler.java index 0a3c91d..0df1012 100644 --- a/graphics/java/android/renderscript/Sampler.java +++ b/graphics/java/android/renderscript/Sampler.java @@ -59,7 +59,6 @@ public class Sampler extends BaseObj { } /** - * @hide * @return minification setting for the sampler */ public Value getMinification() { @@ -67,7 +66,6 @@ public class Sampler extends BaseObj { } /** - * @hide * @return magnification setting for the sampler */ public Value getMagnification() { @@ -75,7 +73,6 @@ public class Sampler extends BaseObj { } /** - * @hide * @return S wrapping mode for the sampler */ public Value getWrapS() { @@ -83,7 +80,6 @@ public class Sampler extends BaseObj { } /** - * @hide * @return T wrapping mode for the sampler */ public Value getWrapT() { @@ -91,7 +87,6 @@ public class Sampler extends BaseObj { } /** - * @hide * @return anisotropy setting for the sampler */ public float getAnisotropy() { @@ -288,7 +283,7 @@ public class Sampler extends BaseObj { public Sampler create() { mRS.validate(); - int id = mRS.nSamplerCreate(mMag.mID, mMin.mID, + int id = mRS.nSamplerCreate(mMag.mID, mMin.mID, mWrapS.mID, mWrapT.mID, mWrapR.mID, mAniso); Sampler sampler = new Sampler(id, mRS); sampler.mMin = mMin; diff --git a/include/androidfw/Input.h b/include/androidfw/Input.h index f8cbdde..a98e1a2 100644 --- a/include/androidfw/Input.h +++ b/include/androidfw/Input.h @@ -811,117 +811,6 @@ private: VelocityTracker mVelocityTracker; }; -/* - * Identifies a device. - */ -struct InputDeviceIdentifier { - inline InputDeviceIdentifier() : - bus(0), vendor(0), product(0), version(0) { - } - - // Information provided by the kernel. - String8 name; - String8 location; - String8 uniqueId; - uint16_t bus; - uint16_t vendor; - uint16_t product; - uint16_t version; - - // A composite input device descriptor string that uniquely identifies the device - // even across reboots or reconnections. The value of this field is used by - // upper layers of the input system to associate settings with individual devices. - // It is hashed from whatever kernel provided information is available. - // Ideally, the way this value is computed should not change between Android releases - // because that would invalidate persistent settings that rely on it. - String8 descriptor; -}; - -/* - * Describes the characteristics and capabilities of an input device. - */ -class InputDeviceInfo { -public: - InputDeviceInfo(); - InputDeviceInfo(const InputDeviceInfo& other); - ~InputDeviceInfo(); - - struct MotionRange { - int32_t axis; - uint32_t source; - float min; - float max; - float flat; - float fuzz; - }; - - void initialize(int32_t id, const String8& name, const String8& descriptor); - - inline int32_t getId() const { return mId; } - inline const String8 getName() const { return mName; } - inline const String8 getDescriptor() const { return mDescriptor; } - inline uint32_t getSources() const { return mSources; } - - const MotionRange* getMotionRange(int32_t axis, uint32_t source) const; - - void addSource(uint32_t source); - void addMotionRange(int32_t axis, uint32_t source, - float min, float max, float flat, float fuzz); - void addMotionRange(const MotionRange& range); - - inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } - inline int32_t getKeyboardType() const { return mKeyboardType; } - - inline void setKeyCharacterMapFile(const String8& value) { mKeyCharacterMapFile = value; } - inline const String8& getKeyCharacterMapFile() const { return mKeyCharacterMapFile; } - - inline const Vector<MotionRange>& getMotionRanges() const { - return mMotionRanges; - } - -private: - int32_t mId; - String8 mName; - String8 mDescriptor; - uint32_t mSources; - int32_t mKeyboardType; - String8 mKeyCharacterMapFile; - - Vector<MotionRange> mMotionRanges; -}; - -/* Types of input device configuration files. */ -enum InputDeviceConfigurationFileType { - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0, /* .idc file */ - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT = 1, /* .kl file */ - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP = 2, /* .kcm file */ -}; - -/* - * Gets the path of an input device configuration file, if one is available. - * Considers both system provided and user installed configuration files. - * - * The device identifier is used to construct several default configuration file - * names to try based on the device name, vendor, product, and version. - * - * Returns an empty string if not found. - */ -extern String8 getInputDeviceConfigurationFilePathByDeviceIdentifier( - const InputDeviceIdentifier& deviceIdentifier, - InputDeviceConfigurationFileType type); - -/* - * Gets the path of an input device configuration file, if one is available. - * Considers both system provided and user installed configuration files. - * - * The name is case-sensitive and is used to construct the filename to resolve. - * All characters except 'a'-'z', 'A'-'Z', '0'-'9', '-', and '_' are replaced by underscores. - * - * Returns an empty string if not found. - */ -extern String8 getInputDeviceConfigurationFilePathByName( - const String8& name, InputDeviceConfigurationFileType type); - } // namespace android #endif // _ANDROIDFW_INPUT_H diff --git a/include/androidfw/InputDevice.h b/include/androidfw/InputDevice.h new file mode 100644 index 0000000..c9554dc --- /dev/null +++ b/include/androidfw/InputDevice.h @@ -0,0 +1,143 @@ +/* + * 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 _ANDROIDFW_INPUT_DEVICE_H +#define _ANDROIDFW_INPUT_DEVICE_H + +#include <androidfw/Input.h> +#include <androidfw/KeyCharacterMap.h> + +namespace android { + +/* + * Identifies a device. + */ +struct InputDeviceIdentifier { + inline InputDeviceIdentifier() : + bus(0), vendor(0), product(0), version(0) { + } + + // Information provided by the kernel. + String8 name; + String8 location; + String8 uniqueId; + uint16_t bus; + uint16_t vendor; + uint16_t product; + uint16_t version; + + // A composite input device descriptor string that uniquely identifies the device + // even across reboots or reconnections. The value of this field is used by + // upper layers of the input system to associate settings with individual devices. + // It is hashed from whatever kernel provided information is available. + // Ideally, the way this value is computed should not change between Android releases + // because that would invalidate persistent settings that rely on it. + String8 descriptor; +}; + +/* + * Describes the characteristics and capabilities of an input device. + */ +class InputDeviceInfo { +public: + InputDeviceInfo(); + InputDeviceInfo(const InputDeviceInfo& other); + ~InputDeviceInfo(); + + struct MotionRange { + int32_t axis; + uint32_t source; + float min; + float max; + float flat; + float fuzz; + }; + + void initialize(int32_t id, const String8& name, const String8& descriptor); + + inline int32_t getId() const { return mId; } + inline const String8 getName() const { return mName; } + inline const String8 getDescriptor() const { return mDescriptor; } + inline uint32_t getSources() const { return mSources; } + + const MotionRange* getMotionRange(int32_t axis, uint32_t source) const; + + void addSource(uint32_t source); + void addMotionRange(int32_t axis, uint32_t source, + float min, float max, float flat, float fuzz); + void addMotionRange(const MotionRange& range); + + inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; } + inline int32_t getKeyboardType() const { return mKeyboardType; } + + inline void setKeyCharacterMap(const sp<KeyCharacterMap>& value) { + mKeyCharacterMap = value; + } + + inline sp<KeyCharacterMap> getKeyCharacterMap() const { + return mKeyCharacterMap; + } + + inline const Vector<MotionRange>& getMotionRanges() const { + return mMotionRanges; + } + +private: + int32_t mId; + String8 mName; + String8 mDescriptor; + uint32_t mSources; + int32_t mKeyboardType; + sp<KeyCharacterMap> mKeyCharacterMap; + + Vector<MotionRange> mMotionRanges; +}; + +/* Types of input device configuration files. */ +enum InputDeviceConfigurationFileType { + INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0, /* .idc file */ + INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT = 1, /* .kl file */ + INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP = 2, /* .kcm file */ +}; + +/* + * Gets the path of an input device configuration file, if one is available. + * Considers both system provided and user installed configuration files. + * + * The device identifier is used to construct several default configuration file + * names to try based on the device name, vendor, product, and version. + * + * Returns an empty string if not found. + */ +extern String8 getInputDeviceConfigurationFilePathByDeviceIdentifier( + const InputDeviceIdentifier& deviceIdentifier, + InputDeviceConfigurationFileType type); + +/* + * Gets the path of an input device configuration file, if one is available. + * Considers both system provided and user installed configuration files. + * + * The name is case-sensitive and is used to construct the filename to resolve. + * All characters except 'a'-'z', 'A'-'Z', '0'-'9', '-', and '_' are replaced by underscores. + * + * Returns an empty string if not found. + */ +extern String8 getInputDeviceConfigurationFilePathByName( + const String8& name, InputDeviceConfigurationFileType type); + +} // namespace android + +#endif // _ANDROIDFW_INPUT_DEVICE_H diff --git a/include/androidfw/KeyCharacterMap.h b/include/androidfw/KeyCharacterMap.h index 679dd2c..3cc1cb2 100644 --- a/include/androidfw/KeyCharacterMap.h +++ b/include/androidfw/KeyCharacterMap.h @@ -19,12 +19,17 @@ #include <stdint.h> +#if HAVE_ANDROID_OS +#include <binder/IBinder.h> +#endif + #include <androidfw/Input.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> #include <utils/Tokenizer.h> #include <utils/String8.h> #include <utils/Unicode.h> +#include <utils/RefBase.h> namespace android { @@ -32,8 +37,10 @@ namespace android { * Describes a mapping from Android key codes to characters. * Also specifies other functions of the keyboard such as the keyboard type * and key modifier semantics. + * + * This object is immutable after it has been loaded. */ -class KeyCharacterMap { +class KeyCharacterMap : public RefBase { public: enum KeyboardType { KEYBOARD_TYPE_UNKNOWN = 0, @@ -50,9 +57,11 @@ public: int32_t metaState; }; - ~KeyCharacterMap(); + /* Loads a key character map from a file. */ + static status_t load(const String8& filename, sp<KeyCharacterMap>* outMap); - static status_t load(const String8& filename, KeyCharacterMap** outMap); + /* Returns an empty key character map. */ + static sp<KeyCharacterMap> empty(); /* Gets the keyboard type. */ int32_t getKeyboardType() const; @@ -92,6 +101,17 @@ public: bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, Vector<KeyEvent>& outEvents) const; +#if HAVE_ANDROID_OS + /* Reads a key map from a parcel. */ + static sp<KeyCharacterMap> readFromParcel(Parcel* parcel); + + /* Writes a key map to a parcel. */ + void writeToParcel(Parcel* parcel) const; +#endif + +protected: + virtual ~KeyCharacterMap(); + private: struct Behavior { Behavior(); @@ -162,6 +182,8 @@ private: status_t parseCharacterLiteral(char16_t* outCharacter); }; + static sp<KeyCharacterMap> sEmpty; + KeyedVector<int32_t, Key*> mKeys; int mType; diff --git a/include/androidfw/KeyLayoutMap.h b/include/androidfw/KeyLayoutMap.h index 5a6f550..e7f22a2 100644 --- a/include/androidfw/KeyLayoutMap.h +++ b/include/androidfw/KeyLayoutMap.h @@ -21,6 +21,7 @@ #include <utils/Errors.h> #include <utils/KeyedVector.h> #include <utils/Tokenizer.h> +#include <utils/RefBase.h> namespace android { @@ -56,29 +57,36 @@ struct AxisInfo { /** * Describes a mapping from keyboard scan codes and joystick axes to Android key codes and axes. + * + * This object is immutable after it has been loaded. */ -class KeyLayoutMap { +class KeyLayoutMap : public RefBase { public: - ~KeyLayoutMap(); - - static status_t load(const String8& filename, KeyLayoutMap** outMap); + static status_t load(const String8& filename, sp<KeyLayoutMap>* outMap); - status_t mapKey(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const; + status_t mapKey(int32_t scanCode, int32_t usageCode, + int32_t* outKeyCode, uint32_t* outFlags) const; status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const; status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const; +protected: + virtual ~KeyLayoutMap(); + private: struct Key { int32_t keyCode; uint32_t flags; }; - KeyedVector<int32_t, Key> mKeys; + KeyedVector<int32_t, Key> mKeysByScanCode; + KeyedVector<int32_t, Key> mKeysByUsageCode; KeyedVector<int32_t, AxisInfo> mAxes; KeyLayoutMap(); + const Key* getKey(int32_t scanCode, int32_t usageCode) const; + class Parser { KeyLayoutMap* mMap; Tokenizer* mTokenizer; diff --git a/include/androidfw/Keyboard.h b/include/androidfw/Keyboard.h index ae65198..6537a8f 100644 --- a/include/androidfw/Keyboard.h +++ b/include/androidfw/Keyboard.h @@ -18,6 +18,7 @@ #define _ANDROIDFW_KEYBOARD_H #include <androidfw/Input.h> +#include <androidfw/InputDevice.h> #include <utils/Errors.h> #include <utils/String8.h> #include <utils/PropertyMap.h> @@ -42,10 +43,10 @@ class KeyCharacterMap; class KeyMap { public: String8 keyLayoutFile; - KeyLayoutMap* keyLayoutMap; + sp<KeyLayoutMap> keyLayoutMap; String8 keyCharacterMapFile; - KeyCharacterMap* keyCharacterMap; + sp<KeyCharacterMap> keyCharacterMap; KeyMap(); ~KeyMap(); diff --git a/include/androidfw/VirtualKeyMap.h b/include/androidfw/VirtualKeyMap.h index 66340e3..dd3ad1e 100644 --- a/include/androidfw/VirtualKeyMap.h +++ b/include/androidfw/VirtualKeyMap.h @@ -43,6 +43,8 @@ struct VirtualKeyDefinition { /** * Describes a collection of virtual keys on a touch screen in terms of * virtual scan codes and hit rectangles. + * + * This object is immutable after it has been loaded. */ class VirtualKeyMap { public: diff --git a/include/private/hwui/DrawGlInfo.h b/include/private/hwui/DrawGlInfo.h index 8028bf3..e33823e 100644 --- a/include/private/hwui/DrawGlInfo.h +++ b/include/private/hwui/DrawGlInfo.h @@ -31,6 +31,10 @@ struct DrawGlInfo { int clipRight; int clipBottom; + // Input: current width/height of destination surface + int width; + int height; + // Input: is the render target an FBO bool isLayer; diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk index a3f92cb..95c77d4 100644 --- a/libs/androidfw/Android.mk +++ b/libs/androidfw/Android.mk @@ -29,6 +29,7 @@ commonUtilsSources:= \ # formerly in libui commonUiSources:= \ Input.cpp \ + InputDevice.cpp \ Keyboard.cpp \ KeyCharacterMap.cpp \ KeyLayoutMap.cpp \ diff --git a/libs/androidfw/Input.cpp b/libs/androidfw/Input.cpp index 2e4b26f..1617a3f 100644 --- a/libs/androidfw/Input.cpp +++ b/libs/androidfw/Input.cpp @@ -1,8 +1,19 @@ -// -// Copyright 2010 The Android Open Source Project -// -// Provides a pipe-based transport for native events in the NDK. -// +/* + * Copyright (C) 2010 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_TAG "Input" //#define LOG_NDEBUG 0 @@ -39,106 +50,6 @@ namespace android { -static const char* CONFIGURATION_FILE_DIR[] = { - "idc/", - "keylayout/", - "keychars/", -}; - -static const char* CONFIGURATION_FILE_EXTENSION[] = { - ".idc", - ".kl", - ".kcm", -}; - -static bool isValidNameChar(char ch) { - return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_'); -} - -static void appendInputDeviceConfigurationFileRelativePath(String8& path, - const String8& name, InputDeviceConfigurationFileType type) { - path.append(CONFIGURATION_FILE_DIR[type]); - for (size_t i = 0; i < name.length(); i++) { - char ch = name[i]; - if (!isValidNameChar(ch)) { - ch = '_'; - } - path.append(&ch, 1); - } - path.append(CONFIGURATION_FILE_EXTENSION[type]); -} - -String8 getInputDeviceConfigurationFilePathByDeviceIdentifier( - const InputDeviceIdentifier& deviceIdentifier, - InputDeviceConfigurationFileType type) { - if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) { - if (deviceIdentifier.version != 0) { - // Try vendor product version. - String8 versionPath(getInputDeviceConfigurationFilePathByName( - String8::format("Vendor_%04x_Product_%04x_Version_%04x", - deviceIdentifier.vendor, deviceIdentifier.product, - deviceIdentifier.version), - type)); - if (!versionPath.isEmpty()) { - return versionPath; - } - } - - // Try vendor product. - String8 productPath(getInputDeviceConfigurationFilePathByName( - String8::format("Vendor_%04x_Product_%04x", - deviceIdentifier.vendor, deviceIdentifier.product), - type)); - if (!productPath.isEmpty()) { - return productPath; - } - } - - // Try device name. - return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type); -} - -String8 getInputDeviceConfigurationFilePathByName( - const String8& name, InputDeviceConfigurationFileType type) { - // Search system repository. - String8 path; - path.setTo(getenv("ANDROID_ROOT")); - path.append("/usr/"); - appendInputDeviceConfigurationFileRelativePath(path, name, type); -#if DEBUG_PROBE - ALOGD("Probing for system provided input device configuration file: path='%s'", path.string()); -#endif - if (!access(path.string(), R_OK)) { -#if DEBUG_PROBE - ALOGD("Found"); -#endif - return path; - } - - // Search user repository. - // TODO Should only look here if not in safe mode. - path.setTo(getenv("ANDROID_DATA")); - path.append("/system/devices/"); - appendInputDeviceConfigurationFileRelativePath(path, name, type); -#if DEBUG_PROBE - ALOGD("Probing for system user input device configuration file: path='%s'", path.string()); -#endif - if (!access(path.string(), R_OK)) { -#if DEBUG_PROBE - ALOGD("Found"); -#endif - return path; - } - - // Not found. -#if DEBUG_PROBE - ALOGD("Probe failed to find input device configuration file: name='%s', type=%d", - name.string(), type); -#endif - return String8(); -} - - // --- InputEvent --- void InputEvent::initialize(int32_t deviceId, int32_t source) { @@ -1222,57 +1133,4 @@ void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) { } } - -// --- InputDeviceInfo --- - -InputDeviceInfo::InputDeviceInfo() { - initialize(-1, String8("uninitialized device info"), String8("unknown")); -} - -InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : - mId(other.mId), mName(other.mName), mDescriptor(other.mDescriptor), - mSources(other.mSources), - mKeyboardType(other.mKeyboardType), - mKeyCharacterMapFile(other.mKeyCharacterMapFile), - mMotionRanges(other.mMotionRanges) { -} - -InputDeviceInfo::~InputDeviceInfo() { -} - -void InputDeviceInfo::initialize(int32_t id, const String8& name, const String8& descriptor) { - mId = id; - mName = name; - mDescriptor = descriptor; - mSources = 0; - mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; - mMotionRanges.clear(); -} - -const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( - int32_t axis, uint32_t source) const { - size_t numRanges = mMotionRanges.size(); - for (size_t i = 0; i < numRanges; i++) { - const MotionRange& range = mMotionRanges.itemAt(i); - if (range.axis == axis && range.source == source) { - return ⦥ - } - } - return NULL; -} - -void InputDeviceInfo::addSource(uint32_t source) { - mSources |= source; -} - -void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, - float flat, float fuzz) { - MotionRange range = { axis, source, min, max, flat, fuzz }; - mMotionRanges.add(range); -} - -void InputDeviceInfo::addMotionRange(const MotionRange& range) { - mMotionRanges.add(range); -} - } // namespace android diff --git a/libs/androidfw/InputDevice.cpp b/libs/androidfw/InputDevice.cpp new file mode 100644 index 0000000..698feb6 --- /dev/null +++ b/libs/androidfw/InputDevice.cpp @@ -0,0 +1,179 @@ +/* + * 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_TAG "InputDevice" + +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> + +#include <androidfw/InputDevice.h> + +namespace android { + +static const char* CONFIGURATION_FILE_DIR[] = { + "idc/", + "keylayout/", + "keychars/", +}; + +static const char* CONFIGURATION_FILE_EXTENSION[] = { + ".idc", + ".kl", + ".kcm", +}; + +static bool isValidNameChar(char ch) { + return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_'); +} + +static void appendInputDeviceConfigurationFileRelativePath(String8& path, + const String8& name, InputDeviceConfigurationFileType type) { + path.append(CONFIGURATION_FILE_DIR[type]); + for (size_t i = 0; i < name.length(); i++) { + char ch = name[i]; + if (!isValidNameChar(ch)) { + ch = '_'; + } + path.append(&ch, 1); + } + path.append(CONFIGURATION_FILE_EXTENSION[type]); +} + +String8 getInputDeviceConfigurationFilePathByDeviceIdentifier( + const InputDeviceIdentifier& deviceIdentifier, + InputDeviceConfigurationFileType type) { + if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) { + if (deviceIdentifier.version != 0) { + // Try vendor product version. + String8 versionPath(getInputDeviceConfigurationFilePathByName( + String8::format("Vendor_%04x_Product_%04x_Version_%04x", + deviceIdentifier.vendor, deviceIdentifier.product, + deviceIdentifier.version), + type)); + if (!versionPath.isEmpty()) { + return versionPath; + } + } + + // Try vendor product. + String8 productPath(getInputDeviceConfigurationFilePathByName( + String8::format("Vendor_%04x_Product_%04x", + deviceIdentifier.vendor, deviceIdentifier.product), + type)); + if (!productPath.isEmpty()) { + return productPath; + } + } + + // Try device name. + return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type); +} + +String8 getInputDeviceConfigurationFilePathByName( + const String8& name, InputDeviceConfigurationFileType type) { + // Search system repository. + String8 path; + path.setTo(getenv("ANDROID_ROOT")); + path.append("/usr/"); + appendInputDeviceConfigurationFileRelativePath(path, name, type); +#if DEBUG_PROBE + ALOGD("Probing for system provided input device configuration file: path='%s'", path.string()); +#endif + if (!access(path.string(), R_OK)) { +#if DEBUG_PROBE + ALOGD("Found"); +#endif + return path; + } + + // Search user repository. + // TODO Should only look here if not in safe mode. + path.setTo(getenv("ANDROID_DATA")); + path.append("/system/devices/"); + appendInputDeviceConfigurationFileRelativePath(path, name, type); +#if DEBUG_PROBE + ALOGD("Probing for system user input device configuration file: path='%s'", path.string()); +#endif + if (!access(path.string(), R_OK)) { +#if DEBUG_PROBE + ALOGD("Found"); +#endif + return path; + } + + // Not found. +#if DEBUG_PROBE + ALOGD("Probe failed to find input device configuration file: name='%s', type=%d", + name.string(), type); +#endif + return String8(); +} + + +// --- InputDeviceInfo --- + +InputDeviceInfo::InputDeviceInfo() { + initialize(-1, String8("uninitialized device info"), String8("unknown")); +} + +InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : + mId(other.mId), mName(other.mName), mDescriptor(other.mDescriptor), + mSources(other.mSources), + mKeyboardType(other.mKeyboardType), + mKeyCharacterMap(other.mKeyCharacterMap), + mMotionRanges(other.mMotionRanges) { +} + +InputDeviceInfo::~InputDeviceInfo() { +} + +void InputDeviceInfo::initialize(int32_t id, const String8& name, const String8& descriptor) { + mId = id; + mName = name; + mDescriptor = descriptor; + mSources = 0; + mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; + mMotionRanges.clear(); +} + +const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( + int32_t axis, uint32_t source) const { + size_t numRanges = mMotionRanges.size(); + for (size_t i = 0; i < numRanges; i++) { + const MotionRange& range = mMotionRanges.itemAt(i); + if (range.axis == axis && range.source == source) { + return ⦥ + } + } + return NULL; +} + +void InputDeviceInfo::addSource(uint32_t source) { + mSources |= source; +} + +void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, + float flat, float fuzz) { + MotionRange range = { axis, source, min, max, flat, fuzz }; + mMotionRanges.add(range); +} + +void InputDeviceInfo::addMotionRange(const MotionRange& range) { + mMotionRanges.add(range); +} + +} // namespace android diff --git a/libs/androidfw/KeyCharacterMap.cpp b/libs/androidfw/KeyCharacterMap.cpp index 6984084..9abbf38 100644 --- a/libs/androidfw/KeyCharacterMap.cpp +++ b/libs/androidfw/KeyCharacterMap.cpp @@ -21,6 +21,11 @@ #include <android/keycodes.h> #include <androidfw/Keyboard.h> #include <androidfw/KeyCharacterMap.h> + +#if HAVE_ANDROID_OS +#include <binder/Parcel.h> +#endif + #include <utils/Log.h> #include <utils/Errors.h> #include <utils/Tokenizer.h> @@ -78,6 +83,8 @@ static String8 toString(const char16_t* chars, size_t numChars) { // --- KeyCharacterMap --- +sp<KeyCharacterMap> KeyCharacterMap::sEmpty = new KeyCharacterMap(); + KeyCharacterMap::KeyCharacterMap() : mType(KEYBOARD_TYPE_UNKNOWN) { } @@ -89,23 +96,23 @@ KeyCharacterMap::~KeyCharacterMap() { } } -status_t KeyCharacterMap::load(const String8& filename, KeyCharacterMap** outMap) { - *outMap = NULL; +status_t KeyCharacterMap::load(const String8& filename, sp<KeyCharacterMap>* outMap) { + outMap->clear(); Tokenizer* tokenizer; status_t status = Tokenizer::open(filename, &tokenizer); if (status) { ALOGE("Error %d opening key character map file %s.", status, filename.string()); } else { - KeyCharacterMap* map = new KeyCharacterMap(); - if (!map) { + sp<KeyCharacterMap> map = new KeyCharacterMap(); + if (!map.get()) { ALOGE("Error allocating key character map."); status = NO_MEMORY; } else { #if DEBUG_PARSER_PERFORMANCE nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); #endif - Parser parser(map, tokenizer); + Parser parser(map.get(), tokenizer); status = parser.parse(); #if DEBUG_PARSER_PERFORMANCE nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; @@ -113,9 +120,7 @@ status_t KeyCharacterMap::load(const String8& filename, KeyCharacterMap** outMap tokenizer->getFilename().string(), tokenizer->getLineNumber(), elapsedTime / 1000000.0); #endif - if (status) { - delete map; - } else { + if (!status) { *outMap = map; } } @@ -124,6 +129,10 @@ status_t KeyCharacterMap::load(const String8& filename, KeyCharacterMap** outMap return status; } +sp<KeyCharacterMap> KeyCharacterMap::empty() { + return sEmpty; +} + int32_t KeyCharacterMap::getKeyboardType() const { return mType; } @@ -419,6 +428,79 @@ void KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents, } } +#if HAVE_ANDROID_OS +sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) { + sp<KeyCharacterMap> map = new KeyCharacterMap(); + map->mType = parcel->readInt32(); + size_t numKeys = parcel->readInt32(); + if (parcel->errorCheck()) { + return NULL; + } + + for (size_t i = 0; i < numKeys; i++) { + int32_t keyCode = parcel->readInt32(); + char16_t label = parcel->readInt32(); + char16_t number = parcel->readInt32(); + if (parcel->errorCheck()) { + return NULL; + } + + Key* key = new Key(); + key->label = label; + key->number = number; + map->mKeys.add(keyCode, key); + + Behavior* lastBehavior = NULL; + while (parcel->readInt32()) { + int32_t metaState = parcel->readInt32(); + char16_t character = parcel->readInt32(); + int32_t fallbackKeyCode = parcel->readInt32(); + if (parcel->errorCheck()) { + return NULL; + } + + Behavior* behavior = new Behavior(); + behavior->metaState = metaState; + behavior->character = character; + behavior->fallbackKeyCode = fallbackKeyCode; + if (lastBehavior) { + lastBehavior->next = behavior; + } else { + key->firstBehavior = behavior; + } + lastBehavior = behavior; + } + + if (parcel->errorCheck()) { + return NULL; + } + } + return map; +} + +void KeyCharacterMap::writeToParcel(Parcel* parcel) const { + parcel->writeInt32(mType); + + size_t numKeys = mKeys.size(); + parcel->writeInt32(numKeys); + for (size_t i = 0; i < numKeys; i++) { + int32_t keyCode = mKeys.keyAt(i); + const Key* key = mKeys.valueAt(i); + parcel->writeInt32(keyCode); + parcel->writeInt32(key->label); + parcel->writeInt32(key->number); + for (const Behavior* behavior = key->firstBehavior; behavior != NULL; + behavior = behavior->next) { + parcel->writeInt32(1); + parcel->writeInt32(behavior->metaState); + parcel->writeInt32(behavior->character); + parcel->writeInt32(behavior->fallbackKeyCode); + } + parcel->writeInt32(0); + } +} +#endif + // --- KeyCharacterMap::Key --- diff --git a/libs/androidfw/KeyLayoutMap.cpp b/libs/androidfw/KeyLayoutMap.cpp index 15d81ee..a7c2199 100644 --- a/libs/androidfw/KeyLayoutMap.cpp +++ b/libs/androidfw/KeyLayoutMap.cpp @@ -47,23 +47,23 @@ KeyLayoutMap::KeyLayoutMap() { KeyLayoutMap::~KeyLayoutMap() { } -status_t KeyLayoutMap::load(const String8& filename, KeyLayoutMap** outMap) { - *outMap = NULL; +status_t KeyLayoutMap::load(const String8& filename, sp<KeyLayoutMap>* outMap) { + outMap->clear(); Tokenizer* tokenizer; status_t status = Tokenizer::open(filename, &tokenizer); if (status) { ALOGE("Error %d opening key layout map file %s.", status, filename.string()); } else { - KeyLayoutMap* map = new KeyLayoutMap(); - if (!map) { + sp<KeyLayoutMap> map = new KeyLayoutMap(); + if (!map.get()) { ALOGE("Error allocating key layout map."); status = NO_MEMORY; } else { #if DEBUG_PARSER_PERFORMANCE nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); #endif - Parser parser(map, tokenizer); + Parser parser(map.get(), tokenizer); status = parser.parse(); #if DEBUG_PARSER_PERFORMANCE nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; @@ -71,9 +71,7 @@ status_t KeyLayoutMap::load(const String8& filename, KeyLayoutMap** outMap) { tokenizer->getFilename().string(), tokenizer->getLineNumber(), elapsedTime / 1000000.0); #endif - if (status) { - delete map; - } else { + if (!status) { *outMap = map; } } @@ -82,32 +80,49 @@ status_t KeyLayoutMap::load(const String8& filename, KeyLayoutMap** outMap) { return status; } -status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const { - ssize_t index = mKeys.indexOfKey(scanCode); - if (index < 0) { +status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t usageCode, + int32_t* outKeyCode, uint32_t* outFlags) const { + const Key* key = getKey(scanCode, usageCode); + if (!key) { #if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d ~ Failed.", scanCode); + ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode); #endif - *keyCode = AKEYCODE_UNKNOWN; - *flags = 0; + *outKeyCode = AKEYCODE_UNKNOWN; + *outFlags = 0; return NAME_NOT_FOUND; } - const Key& k = mKeys.valueAt(index); - *keyCode = k.keyCode; - *flags = k.flags; + *outKeyCode = key->keyCode; + *outFlags = key->flags; #if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d ~ Result keyCode=%d, flags=0x%08x.", scanCode, *keyCode, *flags); + ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d, outFlags=0x%08x.", + scanCode, usageCode, *outKeyCode, *outFlags); #endif return NO_ERROR; } +const KeyLayoutMap::Key* KeyLayoutMap::getKey(int32_t scanCode, int32_t usageCode) const { + if (usageCode) { + ssize_t index = mKeysByUsageCode.indexOfKey(usageCode); + if (index >= 0) { + return &mKeysByUsageCode.valueAt(index); + } + } + if (scanCode) { + ssize_t index = mKeysByScanCode.indexOfKey(scanCode); + if (index >= 0) { + return &mKeysByScanCode.valueAt(index); + } + } + return NULL; +} + status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const { - const size_t N = mKeys.size(); + const size_t N = mKeysByScanCode.size(); for (size_t i=0; i<N; i++) { - if (mKeys.valueAt(i).keyCode == keyCode) { - outScanCodes->add(mKeys.keyAt(i)); + if (mKeysByScanCode.valueAt(i).keyCode == keyCode) { + outScanCodes->add(mKeysByScanCode.keyAt(i)); } } return NO_ERROR; @@ -192,7 +207,7 @@ status_t KeyLayoutMap::Parser::parseKey() { scanCodeToken.string()); return BAD_VALUE; } - if (mMap->mKeys.indexOfKey(scanCode) >= 0) { + if (mMap->mKeysByScanCode.indexOfKey(scanCode) >= 0) { ALOGE("%s: Duplicate entry for key scan code '%s'.", mTokenizer->getLocation().string(), scanCodeToken.string()); return BAD_VALUE; @@ -233,7 +248,7 @@ status_t KeyLayoutMap::Parser::parseKey() { Key key; key.keyCode = keyCode; key.flags = flags; - mMap->mKeys.add(scanCode, key); + mMap->mKeysByScanCode.add(scanCode, key); return NO_ERROR; } diff --git a/libs/androidfw/Keyboard.cpp b/libs/androidfw/Keyboard.cpp index e97a5eb..a84a8c7 100644 --- a/libs/androidfw/Keyboard.cpp +++ b/libs/androidfw/Keyboard.cpp @@ -24,6 +24,7 @@ #include <androidfw/KeycodeLabels.h> #include <androidfw/KeyLayoutMap.h> #include <androidfw/KeyCharacterMap.h> +#include <androidfw/InputDevice.h> #include <utils/Errors.h> #include <utils/Log.h> #include <cutils/properties.h> @@ -32,13 +33,10 @@ namespace android { // --- KeyMap --- -KeyMap::KeyMap() : - keyLayoutMap(NULL), keyCharacterMap(NULL) { +KeyMap::KeyMap() { } KeyMap::~KeyMap() { - delete keyLayoutMap; - delete keyCharacterMap; } status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier, @@ -114,14 +112,12 @@ status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, return NAME_NOT_FOUND; } - KeyLayoutMap* map; - status_t status = KeyLayoutMap::load(path, &map); + status_t status = KeyLayoutMap::load(path, &keyLayoutMap); if (status) { return status; } keyLayoutFile.setTo(path); - keyLayoutMap = map; return OK; } @@ -133,14 +129,12 @@ status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifi return NAME_NOT_FOUND; } - KeyCharacterMap* map; - status_t status = KeyCharacterMap::load(path, &map); + status_t status = KeyCharacterMap::load(path, &keyCharacterMap); if (status) { return status; } keyCharacterMapFile.setTo(path); - keyCharacterMap = map; return OK; } diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 9f2bacd..3910739 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -818,7 +818,10 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, uint32_t width, indent[i] = ' '; } indent[count] = '\0'; - DISPLAY_LIST_LOGD("%sStart display list (%p, %s)", (char*) indent + 2, this, mName.string()); + Rect* clipRect = renderer.getClipRect(); + DISPLAY_LIST_LOGD("%sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f", + (char*) indent + 2, this, mName.string(), clipRect->left, clipRect->top, + clipRect->right, clipRect->bottom); #endif renderer.startMark(mName.string()); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 2a908ab..ebb8eb7 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -249,6 +249,8 @@ status_t OpenGLRenderer::invokeFunctors(Rect& dirty) { info.clipRight = 0; info.clipBottom = 0; info.isLayer = false; + info.width = 0; + info.height = 0; memset(info.transform, 0, sizeof(float) * 16); size_t count = functors.size(); @@ -292,6 +294,8 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) { info.clipRight = clip.right; info.clipBottom = clip.bottom; info.isLayer = hasLayer(); + info.width = getSnapshot()->viewport.getWidth(); + info.height = getSnapshot()->height; getSnapshot()->transform->copyTo(&info.transform[0]); status_t result = (*functor)(DrawGlInfo::kModeDraw, &info); @@ -516,6 +520,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()), bounds.getWidth() / float(layer->getWidth()), 0.0f); layer->setColorFilter(mColorFilter); + layer->setBlend(true); // Save the layer in the snapshot snapshot->flags |= Snapshot::kFlagIsLayer; @@ -1054,6 +1059,10 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, return !mSnapshot->clipRect->isEmpty(); } +Rect* OpenGLRenderer::getClipRect() { + return mSnapshot->clipRect; +} + /////////////////////////////////////////////////////////////////////////////// // Drawing commands /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index b52d2b0..47927bb 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -101,6 +101,7 @@ public: ANDROID_API const Rect& getClipBounds(); ANDROID_API bool quickReject(float left, float top, float right, float bottom); virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); + virtual Rect* getClipRect(); virtual status_t drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, Rect& dirty, int32_t flags, uint32_t level = 0); diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index c7e71eb..41d5c32 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -2237,6 +2237,14 @@ public class AudioManager { * docking station */ public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET; + /** {@hide} The audio output device code for a USB audio accessory. The accessory is in USB host + * mode and the Android device in USB device mode + */ + public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY; + /** {@hide} The audio output device code for a USB audio device. The device is in USB device + * mode and the Android device in USB host mode + */ + public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE; /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be * used in the future in a set method to select whatever default device is chosen by the * platform-specific implementation. diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 2e456f0..48d3712 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -389,9 +389,11 @@ public class AudioService extends IAudioService.Stub { intentFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); intentFilter.addAction(Intent.ACTION_DOCK_EVENT); - intentFilter.addAction(Intent.ACTION_USB_ANLG_HEADSET_PLUG); - intentFilter.addAction(Intent.ACTION_USB_DGTL_HEADSET_PLUG); + intentFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); + intentFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); intentFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG); + intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG); + intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG); intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED); intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); @@ -2800,6 +2802,28 @@ public class AudioService extends IAudioService.Stub { } } + private boolean handleDeviceConnection(boolean connected, int device, String params) { + synchronized (mConnectedDevices) { + boolean isConnected = (mConnectedDevices.containsKey(device) && + mConnectedDevices.get(device).equals(params)); + + if (isConnected && !connected) { + AudioSystem.setDeviceConnectionState(device, + AudioSystem.DEVICE_STATE_UNAVAILABLE, + params); + mConnectedDevices.remove(device); + return true; + } else if (!isConnected && connected) { + AudioSystem.setDeviceConnectionState(device, + AudioSystem.DEVICE_STATE_AVAILABLE, + params); + mConnectedDevices.put(new Integer(device), params); + return true; + } + } + return false; + } + /* cache of the address of the last dock the device was connected to */ private String mDockAddress; @@ -2810,6 +2834,8 @@ public class AudioService extends IAudioService.Stub { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); + int device; + int state; if (action.equals(Intent.ACTION_DOCK_EVENT)) { int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, @@ -2834,15 +2860,15 @@ public class AudioService extends IAudioService.Stub { } AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, + state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); handleA2dpConnectionStateChange(btDevice, state); } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, + state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED); - int device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; + device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; String address = null; BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); @@ -2868,129 +2894,56 @@ public class AudioService extends IAudioService.Stub { address = ""; } - synchronized (mConnectedDevices) { - boolean isConnected = (mConnectedDevices.containsKey(device) && - mConnectedDevices.get(device).equals(address)); - + boolean connected = (state == BluetoothProfile.STATE_CONNECTED); + if (handleDeviceConnection(connected, device, address)) { synchronized (mScoClients) { - if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { - AudioSystem.setDeviceConnectionState(device, - AudioSystem.DEVICE_STATE_UNAVAILABLE, - address); - mConnectedDevices.remove(device); + if (connected) { + mBluetoothHeadsetDevice = btDevice; + } else { mBluetoothHeadsetDevice = null; resetBluetoothSco(); - } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { - AudioSystem.setDeviceConnectionState(device, - AudioSystem.DEVICE_STATE_AVAILABLE, - address); - mConnectedDevices.put(new Integer(device), address); - mBluetoothHeadsetDevice = btDevice; } } } } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) { - int state = intent.getIntExtra("state", 0); + state = intent.getIntExtra("state", 0); int microphone = intent.getIntExtra("microphone", 0); - synchronized (mConnectedDevices) { - if (microphone != 0) { - boolean isConnected = - mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADSET); - if (state == 0 && isConnected) { - AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET, - AudioSystem.DEVICE_STATE_UNAVAILABLE, - ""); - mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADSET); - } else if (state == 1 && !isConnected) { - AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET, - AudioSystem.DEVICE_STATE_AVAILABLE, - ""); - mConnectedDevices.put( - new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADSET), ""); - } - } else { - boolean isConnected = - mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE); - if (state == 0 && isConnected) { - AudioSystem.setDeviceConnectionState( - AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, - AudioSystem.DEVICE_STATE_UNAVAILABLE, - ""); - mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE); - } else if (state == 1 && !isConnected) { - AudioSystem.setDeviceConnectionState( - AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, - AudioSystem.DEVICE_STATE_AVAILABLE, - ""); - mConnectedDevices.put( - new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE), ""); - } - } - } - } else if (action.equals(Intent.ACTION_USB_ANLG_HEADSET_PLUG)) { - int state = intent.getIntExtra("state", 0); - Log.v(TAG, "Broadcast Receiver: Got ACTION_USB_ANLG_HEADSET_PLUG, state = "+state); - synchronized (mConnectedDevices) { - boolean isConnected = - mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET); - if (state == 0 && isConnected) { - AudioSystem.setDeviceConnectionState( - AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, - AudioSystem.DEVICE_STATE_UNAVAILABLE, - ""); - mConnectedDevices.remove(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET); - } else if (state == 1 && !isConnected) { - AudioSystem.setDeviceConnectionState( - AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, - AudioSystem.DEVICE_STATE_AVAILABLE, - ""); - mConnectedDevices.put( - new Integer(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET), ""); - } + if (microphone != 0) { + device = AudioSystem.DEVICE_OUT_WIRED_HEADSET; + } else { + device = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; } + handleDeviceConnection((state == 1), device, ""); + } else if (action.equals(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG)) { + state = intent.getIntExtra("state", 0); + Log.v(TAG, "Broadcast Receiver: Got ACTION_ANALOG_AUDIO_DOCK_PLUG, state = "+state); + handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, ""); } else if (action.equals(Intent.ACTION_HDMI_AUDIO_PLUG)) { - int state = intent.getIntExtra("state", 0); + state = intent.getIntExtra("state", 0); Log.v(TAG, "Broadcast Receiver: Got ACTION_HDMI_AUDIO_PLUG, state = "+state); - synchronized (mConnectedDevices) { - boolean isConnected = - mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_AUX_DIGITAL); - if (state == 0 && isConnected) { - AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL, - AudioSystem.DEVICE_STATE_UNAVAILABLE, - ""); - mConnectedDevices.remove(AudioSystem.DEVICE_OUT_AUX_DIGITAL); - } else if (state == 1 && !isConnected) { - AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL, - AudioSystem.DEVICE_STATE_AVAILABLE, - ""); - mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_AUX_DIGITAL), ""); - } - } - } else if (action.equals(Intent.ACTION_USB_DGTL_HEADSET_PLUG)) { - int state = intent.getIntExtra("state", 0); - Log.v(TAG, "Broadcast Receiver: Got ACTION_USB_DGTL_HEADSET_PLUG, state = "+state); - synchronized (mConnectedDevices) { - boolean isConnected = - mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET); - if (state == 0 && isConnected) { - AudioSystem.setDeviceConnectionState( - AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, - AudioSystem.DEVICE_STATE_UNAVAILABLE, - ""); - mConnectedDevices.remove(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET); - } else if (state == 1 && !isConnected) { - AudioSystem.setDeviceConnectionState( - AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, - AudioSystem.DEVICE_STATE_AVAILABLE, - ""); - mConnectedDevices.put( - new Integer(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET), ""); - } - } + handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_AUX_DIGITAL, ""); + } else if (action.equals(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG)) { + state = intent.getIntExtra("state", 0); + Log.v(TAG, + "Broadcast Receiver Got ACTION_DIGITAL_AUDIO_DOCK_PLUG, state = " + state); + handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, ""); + } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) || + action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) { + state = intent.getIntExtra("state", 0); + int alsaCard = intent.getIntExtra("card", -1); + int alsaDevice = intent.getIntExtra("device", -1); + String params = "card=" + alsaCard + ";device=" + alsaDevice; + device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ? + AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE; + Log.v(TAG, "Broadcast Receiver: Got " + + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ? + "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG") + + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice); + handleDeviceConnection((state == 1), device, params); } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { boolean broadcast = false; - int state = AudioManager.SCO_AUDIO_STATE_ERROR; + int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; synchronized (mScoClients) { int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); // broadcast intent if the connection was initated by AudioService @@ -3002,7 +2955,7 @@ public class AudioService extends IAudioService.Stub { } switch (btState) { case BluetoothHeadset.STATE_AUDIO_CONNECTED: - state = AudioManager.SCO_AUDIO_STATE_CONNECTED; + scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && mScoAudioState != SCO_STATE_DEACTIVATE_REQ && mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { @@ -3010,7 +2963,7 @@ public class AudioService extends IAudioService.Stub { } break; case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: - state = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; + scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; mScoAudioState = SCO_STATE_INACTIVE; clearAllScoClients(0, false); break; @@ -3027,11 +2980,11 @@ public class AudioService extends IAudioService.Stub { } } if (broadcast) { - broadcastScoConnectionState(state); + broadcastScoConnectionState(scoAudioState); //FIXME: this is to maintain compatibility with deprecated intent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); - newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state); + newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); mContext.sendStickyBroadcast(newIntent); } } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 18a00bc..9bafa5c 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -202,6 +202,9 @@ public class AudioSystem public static final int DEVICE_OUT_AUX_DIGITAL = 0x400; public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800; public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000; + public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000; + public static final int DEVICE_OUT_USB_DEVICE = 0x4000; + public static final int DEVICE_OUT_DEFAULT = 0x8000; public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | @@ -216,10 +219,18 @@ public class AudioSystem DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_ANLG_DOCK_HEADSET | DEVICE_OUT_DGTL_DOCK_HEADSET | + DEVICE_OUT_USB_ACCESSORY | + DEVICE_OUT_USB_DEVICE | DEVICE_OUT_DEFAULT); public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER); + public static final int DEVICE_OUT_ALL_SCO = (DEVICE_OUT_BLUETOOTH_SCO | + DEVICE_OUT_BLUETOOTH_SCO_HEADSET | + DEVICE_OUT_BLUETOOTH_SCO_CARKIT); + public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY | + DEVICE_OUT_USB_DEVICE); + // input devices public static final int DEVICE_IN_COMMUNICATION = 0x10000; public static final int DEVICE_IN_AMBIENT = 0x20000; diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java index 11ecd1f..aef631f 100644 --- a/media/java/android/media/MediaMetadataRetriever.java +++ b/media/java/android/media/MediaMetadataRetriever.java @@ -23,6 +23,7 @@ import android.graphics.Bitmap; import android.net.Uri; import java.io.FileDescriptor; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -57,7 +58,24 @@ public class MediaMetadataRetriever * @param path The path of the input media file. * @throws IllegalArgumentException If the path is invalid. */ - public native void setDataSource(String path) throws IllegalArgumentException; + public void setDataSource(String path) throws IllegalArgumentException { + FileInputStream is = null; + try { + is = new FileInputStream(path); + FileDescriptor fd = is.getFD(); + setDataSource(fd, 0, 0x7ffffffffffffffL); + } catch (FileNotFoundException fileEx) { + throw new IllegalArgumentException(); + } catch (IOException ioEx) { + throw new IllegalArgumentException(); + } + + try { + if (is != null) { + is.close(); + } + } catch (Exception e) {} + } /** * Sets the data source (URI) to use. Call this diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index c38f8f3..dd01db6 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -34,7 +34,9 @@ import android.graphics.Bitmap; import android.graphics.SurfaceTexture; import android.media.AudioManager; +import java.io.File; import java.io.FileDescriptor; +import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.util.Map; @@ -847,8 +849,10 @@ public class MediaPlayer * As an alternative, the application could first open the file for reading, * and then use the file descriptor form {@link #setDataSource(FileDescriptor)}. */ - public native void setDataSource(String path) - throws IOException, IllegalArgumentException, SecurityException, IllegalStateException; + public void setDataSource(String path) + throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { + setDataSource(path, null, null); + } /** * Sets the data source (file-path or http/rtsp URL) to use. @@ -875,7 +879,20 @@ public class MediaPlayer ++i; } } - _setDataSource(path, keys, values); + setDataSource(path, keys, values); + } + + private void setDataSource(String path, String[] keys, String[] values) + throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { + File file = new File(path); + if (file.exists()) { + FileInputStream is = new FileInputStream(file); + FileDescriptor fd = is.getFD(); + setDataSource(fd); + is.close(); + } else { + _setDataSource(path, keys, values); + } } private native void _setDataSource( diff --git a/media/java/android/media/audiofx/AcousticEchoCanceler.java b/media/java/android/media/audiofx/AcousticEchoCanceler.java index 7197dd2..e31f84c 100644 --- a/media/java/android/media/audiofx/AcousticEchoCanceler.java +++ b/media/java/android/media/audiofx/AcousticEchoCanceler.java @@ -16,6 +16,8 @@ package android.media.audiofx; +import android.util.Log; + /** * Acoustic Echo Canceler (AEC). * <p>Acoustic Echo Canceler (AEC) is an audio pre-processing which removes the contribution of the @@ -26,14 +28,13 @@ package android.media.audiofx; * <p>An application creates an AcousticEchoCanceler object to instantiate and control an AEC * engine in the audio capture path. * <p>To attach the AcousticEchoCanceler to a particular {@link android.media.AudioRecord}, - * specify the audio session ID of this AudioRecord when constructing the AcousticEchoCanceler. + * specify the audio session ID of this AudioRecord when creating the AcousticEchoCanceler. * The audio session is retrieved by calling * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. * <p>On some devices, an AEC can be inserted by default in the capture path by the platform - * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can - * query which pre-processings are currently applied to an AudioRecord instance by calling - * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the - * AudioRecord. + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application should + * call AcousticEchoCanceler.getEnable() after creating the AEC to check the default AEC activation + * state on a particular AudioRecord session. * <p>See {@link android.media.audiofx.AudioEffect} class for more details on * controlling audio effects. * @hide @@ -44,13 +45,43 @@ public class AcousticEchoCanceler extends AudioEffect { private final static String TAG = "AcousticEchoCanceler"; /** + * Checks if the device implements acoustic echo cancellation. + * @return true if the device implements acoustic echo cancellation, false otherwise. + */ + public static boolean isAvailable() { + return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_AEC); + } + + /** + * Creates an AcousticEchoCanceler and attaches it to the AudioRecord on the audio + * session specified. + * @param audioSession system wide unique audio session identifier. The AcousticEchoCanceler + * will be applied to the AudioRecord with the same audio session. + * @return AcousticEchoCanceler created or null if the device does not implement AEC. + */ + public static AcousticEchoCanceler create(int audioSession) { + AcousticEchoCanceler aec = null; + try { + aec = new AcousticEchoCanceler(audioSession); + } catch (IllegalArgumentException e) { + Log.w(TAG, "not implemented on this device"+ aec); + } catch (UnsupportedOperationException e) { + Log.w(TAG, "not enough resources"); + } catch (RuntimeException e) { + Log.w(TAG, "not enough memory"); + } finally { + return aec; + } + } + + /** * Class constructor. - * <p> The application must catch exceptions when creating an AcousticEchoCanceler as the - * constructor is not guarantied to succeed: + * <p> The constructor is not guarantied to succeed and throws the following exceptions: * <ul> * <li>IllegalArgumentException is thrown if the device does not implement an AEC</li> * <li>UnsupportedOperationException is thrown is the resources allocated to audio * pre-procesing are currently exceeded.</li> + * <li>RuntimeException is thrown if a memory allocation error occurs.</li> * </ul> * * @param audioSession system wide unique audio session identifier. The AcousticEchoCanceler @@ -59,6 +90,7 @@ public class AcousticEchoCanceler extends AudioEffect { * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException + * @hide */ public AcousticEchoCanceler(int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java index 85be267..68a09de 100644 --- a/media/java/android/media/audiofx/AudioEffect.java +++ b/media/java/android/media/audiofx/AudioEffect.java @@ -452,6 +452,22 @@ public class AudioEffect { return (Descriptor[]) native_query_pre_processing(audioSession); } + /** + * Checks if the device implements the specified effect type. + * @param type the requested effect type. + * @return true if the device implements the specified effect type, false otherwise. + * @hide + */ + public static boolean isEffectTypeAvailable(UUID type) { + AudioEffect.Descriptor[] desc = AudioEffect.queryEffects(); + for (int i = 0; i < desc.length; i++) { + if (desc[i].type.equals(type)) { + return true; + } + } + return false; + } + // -------------------------------------------------------------------------- // Control methods // -------------------- diff --git a/media/java/android/media/audiofx/AutomaticGainControl.java b/media/java/android/media/audiofx/AutomaticGainControl.java index 44574f0..eca7eec 100644 --- a/media/java/android/media/audiofx/AutomaticGainControl.java +++ b/media/java/android/media/audiofx/AutomaticGainControl.java @@ -16,24 +16,25 @@ package android.media.audiofx; +import android.util.Log; + /** * Automatic Gain Control (AGC). * <p>Automatic Gain Control (AGC) is an audio pre-processing which automatically normalizes the * output of the captured signal by boosting or lowering input from the microphone to match a preset - * level so that that the output signal level is virtually constant. + * level so that the output signal level is virtually constant. * AGC can be used by applications where the input signal dynamic range is not important but where * a constant strong capture level is desired. * <p>An application creates a AutomaticGainControl object to instantiate and control an AGC * engine in the audio framework. * <p>To attach the AutomaticGainControl to a particular {@link android.media.AudioRecord}, - * specify the audio session ID of this AudioRecord when constructing the AutomaticGainControl. + * specify the audio session ID of this AudioRecord when creating the AutomaticGainControl. * The audio session is retrieved by calling * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. * <p>On some devices, an AGC can be inserted by default in the capture path by the platform - * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can - * query which pre-processings are currently applied to an AudioRecord instance by calling - * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the - * AudioRecord. + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application should + * call AutomaticGainControl.getEnable() after creating the AGC to check the default AGC activation + * state on a particular AudioRecord session. * <p>See {@link android.media.audiofx.AudioEffect} class for more details on * controlling audio effects. * @hide @@ -44,13 +45,43 @@ public class AutomaticGainControl extends AudioEffect { private final static String TAG = "AutomaticGainControl"; /** + * Checks if the device implements automatic gain control. + * @return true if the device implements automatic gain control, false otherwise. + */ + public static boolean isAvailable() { + return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_AGC); + } + + /** + * Creates an AutomaticGainControl and attaches it to the AudioRecord on the audio + * session specified. + * @param audioSession system wide unique audio session identifier. The AutomaticGainControl + * will be applied to the AudioRecord with the same audio session. + * @return AutomaticGainControl created or null if the device does not implement AGC. + */ + public static AutomaticGainControl create(int audioSession) { + AutomaticGainControl agc = null; + try { + agc = new AutomaticGainControl(audioSession); + } catch (IllegalArgumentException e) { + Log.w(TAG, "not implemented on this device "+agc); + } catch (UnsupportedOperationException e) { + Log.w(TAG, "not enough resources"); + } catch (RuntimeException e) { + Log.w(TAG, "not enough memory"); + } finally { + return agc; + } + } + + /** * Class constructor. - * <p> The application must catch exceptions when creating an AutomaticGainControl as the - * constructor is not guarantied to succeed: + * <p> The constructor is not guarantied to succeed and throws the following exceptions: * <ul> * <li>IllegalArgumentException is thrown if the device does not implement an AGC</li> * <li>UnsupportedOperationException is thrown is the resources allocated to audio * pre-procesing are currently exceeded.</li> + * <li>RuntimeException is thrown if a memory allocation error occurs.</li> * </ul> * * @param audioSession system wide unique audio session identifier. The AutomaticGainControl @@ -59,6 +90,7 @@ public class AutomaticGainControl extends AudioEffect { * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException + * @hide */ public AutomaticGainControl(int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { diff --git a/media/java/android/media/audiofx/NoiseSuppressor.java b/media/java/android/media/audiofx/NoiseSuppressor.java index 4e7a8b6..a2d3386 100644 --- a/media/java/android/media/audiofx/NoiseSuppressor.java +++ b/media/java/android/media/audiofx/NoiseSuppressor.java @@ -16,6 +16,8 @@ package android.media.audiofx; +import android.util.Log; + /** * Noise Suppressor (NS). * <p>Noise suppression (NS) is an audio pre-processing which removes background noise from the @@ -27,14 +29,13 @@ package android.media.audiofx; * <p>An application creates a NoiseSuppressor object to instantiate and control an NS * engine in the audio framework. * <p>To attach the NoiseSuppressor to a particular {@link android.media.AudioRecord}, - * specify the audio session ID of this AudioRecord when constructing the NoiseSuppressor. + * specify the audio session ID of this AudioRecord when creating the NoiseSuppressor. * The audio session is retrieved by calling * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. * <p>On some devices, NS can be inserted by default in the capture path by the platform - * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can - * query which pre-processings are currently applied to an AudioRecord instance by calling - * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the - * AudioRecord. + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application should + * call NoiseSuppressor.getEnable() after creating the NS to check the default NS activation + * state on a particular AudioRecord session. * <p>See {@link android.media.audiofx.AudioEffect} class for more details on * controlling audio effects. * @hide @@ -45,13 +46,44 @@ public class NoiseSuppressor extends AudioEffect { private final static String TAG = "NoiseSuppressor"; /** + * Checks if the device implements noise suppression. + * @return true if the device implements noise suppression, false otherwise. + */ + public static boolean isAvailable() { + return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_NS); + } + + /** + * Creates a NoiseSuppressor and attaches it to the AudioRecord on the audio + * session specified. + * @param audioSession system wide unique audio session identifier. The NoiseSuppressor + * will be applied to the AudioRecord with the same audio session. + * @return NoiseSuppressor created or null if the device does not implement noise + * suppression. + */ + public static NoiseSuppressor create(int audioSession) { + NoiseSuppressor ns = null; + try { + ns = new NoiseSuppressor(audioSession); + } catch (IllegalArgumentException e) { + Log.w(TAG, "not implemented on this device "+ns); + } catch (UnsupportedOperationException e) { + Log.w(TAG, "not enough resources"); + } catch (RuntimeException e) { + Log.w(TAG, "not enough memory"); + } finally { + return ns; + } + } + + /** * Class constructor. - * <p> The application must catch exceptions when creating an NoiseSuppressor as the - * constructor is not guarantied to succeed: + * <p> The constructor is not guarantied to succeed and throws the following exceptions: * <ul> * <li>IllegalArgumentException is thrown if the device does not implement an NS</li> * <li>UnsupportedOperationException is thrown is the resources allocated to audio * pre-procesing are currently exceeded.</li> + * <li>RuntimeException is thrown if a memory allocation error occurs.</li> * </ul> * * @param audioSession system wide unique audio session identifier. The NoiseSuppressor @@ -60,8 +92,9 @@ public class NoiseSuppressor extends AudioEffect { * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException + * @hide */ - public NoiseSuppressor(int audioSession) + private NoiseSuppressor(int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { super(EFFECT_TYPE_NS, EFFECT_TYPE_NULL, 0, audioSession); } diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp index 0dc3b65..297dadf 100644 --- a/media/jni/android_media_MediaMetadataRetriever.cpp +++ b/media/jni/android_media_MediaMetadataRetriever.cpp @@ -131,13 +131,6 @@ android_media_MediaMetadataRetriever_setDataSourceAndHeaders( "setDataSource failed"); } - -static void android_media_MediaMetadataRetriever_setDataSource( - JNIEnv *env, jobject thiz, jstring path) { - android_media_MediaMetadataRetriever_setDataSourceAndHeaders( - env, thiz, path, NULL, NULL); -} - static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) { ALOGV("setDataSource"); @@ -447,8 +440,6 @@ static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobje // JNI mapping between Java methods and native methods static JNINativeMethod nativeMethods[] = { - {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaMetadataRetriever_setDataSource}, - { "_setDataSource", "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V", diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 2e74ffd..5eadb3a 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -216,12 +216,6 @@ android_media_MediaPlayer_setDataSourceAndHeaders( } static void -android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path) -{ - android_media_MediaPlayer_setDataSourceAndHeaders(env, thiz, path, NULL, NULL); -} - -static void android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length) { sp<MediaPlayer> mp = getMediaPlayer(env, thiz); @@ -825,8 +819,6 @@ android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { - {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource}, - { "_setDataSource", "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V", diff --git a/native/android/input.cpp b/native/android/input.cpp index 6eb2990..accec64 100644 --- a/native/android/input.cpp +++ b/native/android/input.cpp @@ -32,7 +32,6 @@ using android::InputEvent; using android::KeyEvent; using android::MotionEvent; -using android::InputDeviceInfo; using android::sp; using android::Vector; diff --git a/native/android/native_window.cpp b/native/android/native_window.cpp index c58ee00..99c0fd3 100644 --- a/native/android/native_window.cpp +++ b/native/android/native_window.cpp @@ -60,13 +60,16 @@ int32_t ANativeWindow_getFormat(ANativeWindow* window) { int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width, int32_t height, int32_t format) { - int32_t err = native_window_set_buffers_geometry(window, width, height, format); + int32_t err = native_window_set_buffers_format(window, format); if (!err) { - int mode = NATIVE_WINDOW_SCALING_MODE_FREEZE; - if (width && height) { - mode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - } - err = native_window_set_scaling_mode(window, mode); + err = native_window_set_buffers_user_dimensions(window, width, height); + if (!err) { + int mode = NATIVE_WINDOW_SCALING_MODE_FREEZE; + if (width && height) { + mode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + } + err = native_window_set_scaling_mode(window, mode); + } } return err; } diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index c937a09..2a4d59b 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -1459,7 +1459,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback Log.w("GLThread", "egl createSurface"); } if (!mEglHelper.createSurface()) { - mSurfaceIsBad = true; + synchronized(sGLThreadManager) { + mSurfaceIsBad = true; + sGLThreadManager.notifyAll(); + } continue; } createEglSurface = false; @@ -1519,7 +1522,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback // but we haven't been notified yet. // Log the error to help developers understand why rendering stopped. EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError); - mSurfaceIsBad = true; + + synchronized(sGLThreadManager) { + mSurfaceIsBad = true; + sGLThreadManager.notifyAll(); + } break; } diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_panel.xml index f6ed804..b712dba 100644 --- a/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_panel.xml +++ b/packages/SystemUI/res/layout-sw600dp/status_bar_input_methods_panel.xml @@ -21,7 +21,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="match_parent" - android:paddingBottom="28dip" + android:paddingBottom="7dip" android:orientation="vertical" android:visibility="gone"> <View @@ -38,7 +38,7 @@ android:layout_height="wrap_content" android:layout_marginLeft="20dip" android:orientation="vertical" - android:background="@*android:drawable/dialog_full_holo_dark"> + android:background="@drawable/notify_panel_clock_bg"> <!-- Hard keyboard switch --> <LinearLayout android:id="@+id/hard_keyboard_section" @@ -51,7 +51,7 @@ android:orientation="horizontal"> <TextView android:id="@+id/use_physical_keyboard_label" - android:layout_width="wrap_content" + android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" android:minHeight="?android:attr/listPreferredItemHeight" @@ -82,7 +82,7 @@ <!-- Input method list --> <ScrollView android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_height="0dip" android:overScrollMode="ifContentScrolls" android:layout_marginTop="3dip" android:layout_weight="1" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 08dedfa..56826fa 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Kennisgewings"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-verbind"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Stel invoer metodes op"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Gebruik fisiese sleutelbord"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Laat die program <xliff:g id="APPLICATION">%1$s</xliff:g> toe om toegang tot die USB-toestel te kry?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Laat die program <xliff:g id="APPLICATION">%1$s</xliff:g> toe om toegang tot die USB-toebehoorsel te kry?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Maak <xliff:g id="ACTIVITY">%1$s</xliff:g> oop wanneer hierdie USB-toestel gekoppel is?"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 13aaacb..7013862 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"ማሳወቂያዎች"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"ብሉቱዝ አያይዝ"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"የግቤት ስልቶችን አዘጋጅ"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"የቁልፍ ሰሌዳ ተጠቀም"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"መተግበሪያ <xliff:g id="APPLICATION">%1$s</xliff:g> የUSB መሣሪያን ለመድረስ ይፍቀድ?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"መተግበሪያ <xliff:g id="APPLICATION">%1$s</xliff:g> የUSB ተቀጥላ ላይ እንዲደርስ ፍቀድ?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"የዚህ USB ተቀጥላ ሲያያዝ <xliff:g id="ACTIVITY">%1$s</xliff:g>ይከፈት?"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 4bc56af..201f72c 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"التنبيهات"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"تم إنشاء الاتصال بالإنترنت عن طريق البلوتوث."</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"إعداد أسلوب الإدخال"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"استخدام لوحة المفاتيح الفعلية"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"هل تريد السماح للتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى جهاز USB؟"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"هل تريد السماح للتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى ملحق USB؟"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"هل تريد فتح <xliff:g id="ACTIVITY">%1$s</xliff:g> عند توصيل جهاز USB هذا؟"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index d083467..b885503 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Паведамленні"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Прывязаныя праз Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Налада метадаў уводу"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Выкарыст. фiзiч. клав."</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Дазволіць праыкладанню <xliff:g id="APPLICATION">%1$s</xliff:g> атрымлiваць доступ да прылады USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Дазволіць прыкладанню <xliff:g id="APPLICATION">%1$s</xliff:g> доступ да прылады USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Адкрыць <xliff:g id="ACTIVITY">%1$s</xliff:g>, калі гэтая USB-прылада падлучаная?"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 33aca92..e5167a5 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Известия"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth има връзка с тетъринг"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Методи на въвеждане: Настройка"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Използване на физ. клав."</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Да се разреши ли на приложението <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до USB устройството?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Да се разреши ли на приложението <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до аксесоара за USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Да се отвори ли <xliff:g id="ACTIVITY">%1$s</xliff:g>, когато това USB устройство е свързано?"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 775e610..0ebced0 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificacions"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth sense fil"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura els mètodes d\'entrada"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilitza un teclat físic"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vols permetre que l\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi al dispositiu USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vols permetre que l\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a l\'accessori USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vols que s\'obri <xliff:g id="ACTIVITY">%1$s</xliff:g> quan aquest dispositiu USB estigui connectat?"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 0f48f35..847bfc4 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Oznámení"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Datové připojení Bluetooth se sdílí"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavit metody vstupu"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Použít fyz. klávesnici"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k perifernímu zařízení USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Chcete při připojení tohoto zařízení USB otevřít aplikaci <xliff:g id="ACTIVITY">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index b518898..ac58b06 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Underretninger"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-tethering anvendt"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inputmetoder"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Brug fysisk tastatur"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Tillad, at appen <xliff:g id="APPLICATION">%1$s</xliff:g> kan få adgang til USB-enheden?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vil du tillade, at appen <xliff:g id="APPLICATION">%1$s</xliff:g> får adgang til USB-enheden?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vil du åbne <xliff:g id="ACTIVITY">%1$s</xliff:g>, når denne USB-enhed er tilsluttet?"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index ab4eeb4..39d5c33 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Benachrichtigungen"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-Tethering aktiv"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Eingabemethoden einrichten"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Physische Tastatur"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"App <xliff:g id="APPLICATION">%1$s</xliff:g> Zugriff auf USB-Gerät gewähren?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"App <xliff:g id="APPLICATION">%1$s</xliff:g> Zugriff auf USB-Zubehör gewähren?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"<xliff:g id="ACTIVITY">%1$s</xliff:g> öffnen, wenn dieses USB-Gerät verbunden ist?"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index cc9dce1..48158db 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Ειδοποιήσεις"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Έγινε σύνδεση μέσω Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Ρύθμιση μεθόδων εισαγωγής"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Χρήση κανονικού πληκτρολ."</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στη συσκευή USB;"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στο αξεσουάρ USB;"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Άνοιγμα του <xliff:g id="ACTIVITY">%1$s</xliff:g> κατά τη σύνδεση αυτής της συσκευής USB;"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 3c70b15..148924a 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifications"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tethered"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Set up input methods"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Use physical keyboard"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Allow the app <xliff:g id="APPLICATION">%1$s</xliff:g> to access the USB device?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Allow the app <xliff:g id="APPLICATION">%1$s</xliff:g> to access the USB accessory?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Open <xliff:g id="ACTIVITY">%1$s</xliff:g> when this USB device is connected?"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index a700908..4db7130 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificaciones"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de intro."</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Usar teclado físico"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"¿Deseas que la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al dispositivo USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"¿Deseas que la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al accesorio USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"¿Abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> cuando este dispositivo USB esté conectado?"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index f0dcc23..f7f73d7 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificaciones"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de introducción"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizar teclado físico"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"¿Permitir que la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al dispositivo USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"¿Permitir que la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda al accesorio USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"¿Quieres abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> al conectar este dispositivo USB?"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 16bb040..8e3a1e3 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Teatised"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth on jagatud"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Seadista sisestusmeetodeid"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Kasutage füüsilist klaviatuuri"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Kas lubate rakendusel <xliff:g id="APPLICATION">%1$s</xliff:g> USB-seadmele juurde pääseda?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Kas lubate rakendusel <xliff:g id="APPLICATION">%1$s</xliff:g> USB-seadmele juurde pääseda?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Kas avada <xliff:g id="ACTIVITY">%1$s</xliff:g>, kui see USB-seade on ühendatud?"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 91a8f64..569e929 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"اعلان ها"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"اتصال اینترنتی با بلوتوث تلفن همراه"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"تنظیم روشهای ورودی"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"از صفحه کلید فیزیکی استفاده کنید"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه می دهید به دستگاه USB دسترسی داشته باشد؟"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"به برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه میدهد تا به وسیله جانبی USB دسترسی داشته باشد؟"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"وقتی این دستگاه USB وصل است، <xliff:g id="ACTIVITY">%1$s</xliff:g> باز شود؟"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index cf9230c7..93e6b62 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Ilmoitukset"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth yhdistetty"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Määritä syöttötavat"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Käytä fyysistä näppäimistöä"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Annetaanko sovellukselle <xliff:g id="APPLICATION">%1$s</xliff:g> lupa käyttää USB-laitetta?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Annetaanko sovellukselle <xliff:g id="APPLICATION">%1$s</xliff:g> lupa käyttää USB-lisälaitetta?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Avataanko <xliff:g id="ACTIVITY">%1$s</xliff:g> tämän USB-laitteen ollessa kytkettynä?"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index d313517..1a8c6a7 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifications"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Connexion Bluetooth partagée"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurer les modes de saisie"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utiliser clavier physique"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Autoriser l\'application <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder au périphérique USB ?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Autoriser l\'application <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à l\'accessoire USB ?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Ouvrir <xliff:g id="ACTIVITY">%1$s</xliff:g> lors de la connexion de ce périphérique USB ?"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 42b901c..741f1b4 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"सूचनाएं"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth टीदर किया गया"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट पद्धति सेट करें"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"भौतिक कीबोर्ड का उपयोग करें"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"एप्लिकेशन <xliff:g id="APPLICATION">%1$s</xliff:g> को USB उपकरण तक पहुंचने दें?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"एप्लिकेशन <xliff:g id="APPLICATION">%1$s</xliff:g> को USB सहायक उपकरण तक पहुंचने दें?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"जब यह USB उपकरण कनेक्ट किया जाए, तब <xliff:g id="ACTIVITY">%1$s</xliff:g> को खोलें?"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 4e6d99c..f3d4043 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Obavijesti"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth posredno povezan"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Postavljanje načina unosa"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Rabi fizičku tipkovnicu"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> da pristupi ovom USB uređaju?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> da pristupi ovom USB dodatku?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Otvoriti <xliff:g id="ACTIVITY">%1$s</xliff:g> kad se spoji ovaj USB uređaj?"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index e710d50..1c28b57 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Értesítések"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth megosztva"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Beviteli módok beállítása"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Valódi bill. használata"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás hozzáférhet az USB-eszközhöz?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás hozzáférhet az USB-kiegészítőhöz?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"<xliff:g id="ACTIVITY">%1$s</xliff:g> megnyitása, ha USB-kiegészítő csatlakoztatva van?"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 2acf554..267f5e7 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pemberitahuan"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tertambat"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Menyiapkan metode masukan"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Gunakan keyboard fisik"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Izinkan apl <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses perangkat USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Izinkan apl <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses aksesori USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Buka <xliff:g id="ACTIVITY">%1$s</xliff:g> ketika perangkat USB ini tersambung?"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 0119d5c..cdf7c9d 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifiche"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth con tethering"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configura metodi di immissione"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizza tastiera fisica"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Consentire all\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere al dispositivo USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Consentire all\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere all\'accessorio USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Aprire <xliff:g id="ACTIVITY">%1$s</xliff:g> quando questo dispositivo USB è collegato?"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index b6376c8..bc5e873 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"התראות"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth קשור"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"הגדר שיטות קלט"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"השתמש במקלדת הפיזית"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"לאפשר ליישום <xliff:g id="APPLICATION">%1$s</xliff:g> גישה להתקן ה-USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"לאפשר ליישום <xliff:g id="APPLICATION">%1$s</xliff:g> גישה לאביזר ה-USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"האם לפתוח את <xliff:g id="ACTIVITY">%1$s</xliff:g> כאשר מכשיר USB זה מחובר?"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index d9c9aa2..01d76eb 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetoothテザリング接続"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"入力方法をセットアップ"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"物理キーボードを使用"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"アプリ「<xliff:g id="APPLICATION">%1$s</xliff:g>」にUSBデバイスへのアクセスを許可しますか?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"アプリ「<xliff:g id="APPLICATION">%1$s</xliff:g>」にUSBアクセサリへのアクセスを許可しますか?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"このUSBデバイスが接続されたときに<xliff:g id="ACTIVITY">%1$s</xliff:g>を開きますか?"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 79569c5..88194df 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"알림"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"블루투스 테더링됨"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"입력 방법 설정"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"물리적 키보드 사용"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 USB 기기에 액세스하도록 허용하시겠습니까?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 USB 액세서리에 액세스하도록 허용하시겠습니까?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"USB 기기가 연결될 때 <xliff:g id="ACTIVITY">%1$s</xliff:g>(을)를 여시겠습니까?"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 490bd4a..942e159 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pranešimai"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"„Bluetooth“ susieta"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nustatyti įvesties metodus"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Naudoti fizinę klaviatūrą"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Leisti programai „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti USB įrenginį?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Leisti programai „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti USB priedą?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Atidaryti <xliff:g id="ACTIVITY">%1$s</xliff:g>, kai prijungtas šis USB įrenginys?"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 62e99ee..b5c9130 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Paziņojumi"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth piesaiste"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Iestatīt ievades metodes"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Izmantot fizisku tastatūru"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vai ļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šai USB ierīcei?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vai ļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šim USB piederumam?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vai atvērt darbību <xliff:g id="ACTIVITY">%1$s</xliff:g>, kad tiek pievienota šī USB ierīce?"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 5f64f7b..f08013d 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Pemberitahuan"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ditambatkan"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Sediakan kaedah input"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Guna ppn kekunci fizikal"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Benarkan aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses peranti USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Benarkan aplikasi <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses aksesori USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Buka <xliff:g id="ACTIVITY">%1$s</xliff:g> apabila peranti USB ini disambungkan?"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index b90876a..fdd3b10 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Varslinger"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tilknyttet"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inndatametoder"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Bruk fysisk tastatur"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vil du gi appen <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til USB-enheten?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vil du gi appen <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til USB-tilbehøret?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vil du åpne <xliff:g id="ACTIVITY">%1$s</xliff:g> når denne USB-enheten er tilkoblet?"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index cf85c75..5314ba3 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Meldingen"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth getetherd"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Invoermethoden instellen"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Fysiek toetsenbord gebruiken"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"De app <xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot het USB-apparaat?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"De app <xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot het USB-accessoire?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"<xliff:g id="ACTIVITY">%1$s</xliff:g> openen wanneer dit USB-apparaat wordt aangesloten?"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index c65f99e..26e3989 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Powiadomienia"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth – podłączono"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfiguruj metody wprowadzania"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Używaj klawiatury fizycznej"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Czy otworzyć <xliff:g id="ACTIVITY">%1$s</xliff:g> po podłączeniu tego urządzenia USB?"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index e1340ec..a5999e3 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificações"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth ligado"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos introdução"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizar teclado físico"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Permitir que a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao dispositivo USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permitir que a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao acessório USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> quando este dispositivo USB estiver ligado?"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index dec4def..02bef77 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificações"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth vinculado"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurar métodos de entrada"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Usar o teclado físico"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Permitir que o aplicativo <xliff:g id="APPLICATION">%1$s</xliff:g> acesse o dispositivo USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permitir que o aplicativo <xliff:g id="APPLICATION">%1$s</xliff:g> acesse o acessório USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Abrir <xliff:g id="ACTIVITY">%1$s</xliff:g> quando este dispositivo USB estiver conectado?"</string> diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml index 983df47..3062d48 100644 --- a/packages/SystemUI/res/values-rm/strings.xml +++ b/packages/SystemUI/res/values-rm/strings.xml @@ -66,7 +66,7 @@ <skip /> <!-- no translation found for status_bar_input_method_settings_configure_input_methods (3504292471512317827) --> <skip /> - <!-- no translation found for status_bar_use_physical_keyboard (3695516942412442936) --> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> <skip /> <!-- no translation found for usb_device_permission_prompt (834698001271562057) --> <skip /> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index e4c55d6..ff6ca3d 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notificări"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Conectat prin tethering prin Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configuraţi metode de intrare"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Utilizaţi tastat. fizică"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Permiteţi aplicaţiei <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze dispozitivul USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Permiteţi aplicaţiei <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze accesoriul USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Deschideţi <xliff:g id="ACTIVITY">%1$s</xliff:g> la conectarea acestui dispozitiv USB?"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 963976d..4057599 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Уведомления"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Общий модем доступен через Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Настройка способов ввода"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Использовать физическую клавиатуру"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Открыть приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к USB-устройству?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Открыть приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к USB-устройству?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Запускать <xliff:g id="ACTIVITY">%1$s</xliff:g> при подключении этого USB-устройства?"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index f0ec8ff..67368ac 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Upozornenia"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Zdieľané dátové pripojenie cez Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavenie metód vstupu"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Použiť fyzickú klávesnicu"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k periférnemu zariadeniu USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Chcete pri pripojení tohto zariadenia USB otvoriť aplikáciu <xliff:g id="ACTIVITY">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 61b82c9..77aef3d 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Obvestila"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Internetna povezava prek Bluetootha"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Nastavi načine vnosa"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Uporabi fizično tipkovn."</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Želite programu <xliff:g id="APPLICATION">%1$s</xliff:g> dovoliti dostop do naprave USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Želite dovoliti programu <xliff:g id="APPLICATION">%1$s</xliff:g> dostop do dodatka USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Želite, da se odpre <xliff:g id="ACTIVITY">%1$s</xliff:g>, ko priključite to napravo USB?"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index f341fba..3268544 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Обавештења"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Веза преко Bluetooth-а"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Подеси методе уноса"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Користи физичку тастатуру"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Желите ли да дозволите апликацији <xliff:g id="APPLICATION">%1$s</xliff:g> да приступа USB уређају?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Желите ли да дозволите апликацији <xliff:g id="APPLICATION">%1$s</xliff:g> да приступа USB помоћном уређају?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Желите ли да се отвори <xliff:g id="ACTIVITY">%1$s</xliff:g> када се прикључи овај USB уређај?"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index f8fb054..ba4edea 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Aviseringar"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Internetdelning via Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurera inmatningsmetoder"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Använd fysiska tangenter"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vill du tillåta att appen <xliff:g id="APPLICATION">%1$s</xliff:g> använder USB-enheten?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vill du tillåta att appen <xliff:g id="APPLICATION">%1$s</xliff:g> använder USB-tillbehöret?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vill du öppna <xliff:g id="ACTIVITY">%1$s</xliff:g> när den här USB-enheten ansluts?"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 70e29eb..8a6b050 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -46,7 +46,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Arifa"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth imefungwa"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Weka mbinu za ingizo"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Tumia kibodi halisi"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Ruhusu programu <xliff:g id="APPLICATION">%1$s</xliff:g> kufikia kifaa cha USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Ruhusu programu <xliff:g id="APPLICATION">%1$s</xliff:g> kufikia kifaa cha ziada cha USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Je, ungetaka kufungua <xliff:g id="ACTIVITY">%1$s</xliff:g>wakati kifaa cha USB kimeunganishwa?"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 3f37060..42c4721 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"การแจ้งเตือน"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"บลูทูธที่ปล่อยสัญญาณ"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ตั้งค่าวิธีการป้อนข้อมูล"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"ใช้แป้นพิมพ์จริง"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"อนุญาตให้แอปพลิเคชัน <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึงอุปกรณ์ USB นี้หรือไม่"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"อนุญาตให้แอปพลิเคชัน <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึงอุปกรณ์เสริม USB นี้หรือไม่"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"เปิด <xliff:g id="ACTIVITY">%1$s</xliff:g> เมื่อมีการเชื่อมต่ออุปกรณ์ USB นี้หรือไม่"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 807d797..55ecfae 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Mga Notification"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Na-tether ang bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"I-set up paraan ng pag-input"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Gamitin ang pisikal na keyboard"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Payagan ang app na <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang USB device?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Payagan ang app na <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang USB accessory?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Buksan ang <xliff:g id="ACTIVITY">%1$s</xliff:g> kapag nakakonekta ang USB device na ito?"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 83567ae..f0aa516 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Bildirimler"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth paylaşımı tamam"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Giriş yöntemlerini ayarla"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Fiziksel klavyeyi kullan"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının USB cihazına erişmesine izin verilsin mi?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının USB aksesuarına erişmesine izin verilsin mi?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Bu USB cihaz bağlandığında <xliff:g id="ACTIVITY">%1$s</xliff:g> açılsın mı?"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index bec231a..9a05919 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Сповіщення"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Створено прив\'язку Bluetooth"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Налаштувати методи введення"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Викор. реальну клавіатуру"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Надати програмі <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до пристрою USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Надати програмі <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до аксесуара USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Відкривати \"<xliff:g id="ACTIVITY">%1$s</xliff:g>\", коли під’єднано пристрій USB?"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 34b84af..abd024a 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Thông báo"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth được dùng làm điểm truy cập Internet"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Thiết lập phương thức nhập"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Sử dụng bàn phím vật lý"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Cho phép ứng dụng <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập thiết bị USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Cho phép ứng dụng <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập phụ kiện USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Mở <xliff:g id="ACTIVITY">%1$s</xliff:g> khi thiết bị USB này được kết nối?"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 1f9c959..ec92713 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"已通过蓝牙共享网络"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"设置输入法"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"使用物理键盘"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"允许应用“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该 USB 设备吗?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"允许应用“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问该 USB 配件吗?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"要在连接此 USB 设备时打开<xliff:g id="ACTIVITY">%1$s</xliff:g>吗?"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 614f143..cabc243 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"藍牙網路共用已開"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"設定輸入法"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"使用實體鍵盤"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"允許 <xliff:g id="APPLICATION">%1$s</xliff:g> 應用程式存取 USB 裝置嗎?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"允許 <xliff:g id="APPLICATION">%1$s</xliff:g> 應用程式存取 USB 配件嗎?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"連接這個 USB 裝置時啟用 <xliff:g id="ACTIVITY">%1$s</xliff:g> 嗎?"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 0249e89..27dd8fd 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -48,7 +48,8 @@ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Izaziso"</string> <string name="bluetooth_tethered" msgid="7094101612161133267">"Ukusebenzisa i-Bluetooth njengemodemu"</string> <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Izilungiselelo zezindlela zokufakwayo"</string> - <string name="status_bar_use_physical_keyboard" msgid="3695516942412442936">"Sebenzisa ikhibhodi ebangekayo"</string> + <!-- no translation found for status_bar_use_physical_keyboard (7551903084416057810) --> + <skip /> <string name="usb_device_permission_prompt" msgid="834698001271562057">"Vumela insiza <xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ufinyelele ezintweni eziphuma ne-USB?"</string> <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Vumela insiza <xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ufinyelele ezintweni eziphuma ne-USB?"</string> <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Vula <xliff:g id="ACTIVITY">%1$s</xliff:g> uma ledivayisi ye-USB ixhunyiwe?"</string> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index fc81f8e..6dbe9d3 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -125,7 +125,7 @@ <string name="status_bar_input_method_settings_configure_input_methods">Set up input methods</string> <!-- Label of a toggle switch to disable use of the physical keyboard in favor of the IME. [CHAR LIMIT=25] --> - <string name="status_bar_use_physical_keyboard">Use physical keyboard</string> + <string name="status_bar_use_physical_keyboard">Physical keyboard</string> <!-- Prompt for the USB device permission dialog [CHAR LIMIT=80] --> <string name="usb_device_permission_prompt">Allow the app <xliff:g id="application">%1$s</xliff:g> to access the USB device?</string> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 5ba72c7..3f611fc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -591,10 +591,14 @@ public class PhoneStatusBar extends BaseStatusBar { } final StatusBarNotification oldNotification = oldEntry.notification; - final RemoteViews oldContentView = oldNotification.notification.contentView; - - final RemoteViews contentView = notification.notification.contentView; + // XXX: modify when we do something more intelligent with the two content views + final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null) + ? oldNotification.notification.bigContentView + : oldNotification.notification.contentView; + final RemoteViews contentView = (notification.notification.bigContentView != null) + ? notification.notification.bigContentView + : notification.notification.contentView; if (DEBUG) { Slog.d(TAG, "old notification: when=" + oldNotification.notification.when @@ -2043,7 +2047,10 @@ public class PhoneStatusBar extends BaseStatusBar { snapshot.add(child); } } - final int N = snapshot.size(); + if (snapshot.isEmpty()) { + animateCollapse(false); + return; + } new Thread(new Runnable() { @Override public void run() { @@ -2059,6 +2066,7 @@ public class PhoneStatusBar extends BaseStatusBar { mPile.setViewRemoval(false); mPostCollapseCleanup = new Runnable() { + @Override public void run() { try { mPile.setViewRemoval(true); @@ -2069,9 +2077,8 @@ public class PhoneStatusBar extends BaseStatusBar { View sampleView = snapshot.get(0); int width = sampleView.getWidth(); - final int velocity = (int)(width * 8); // 1000/8 = 125 ms duration - for (View v : snapshot) { - final View _v = v; + final int velocity = width * 8; // 1000/8 = 125 ms duration + for (final View _v : snapshot) { mHandler.postDelayed(new Runnable() { @Override public void run() { @@ -2087,6 +2094,7 @@ public class PhoneStatusBar extends BaseStatusBar { // synchronize the end of those animations with the start of the collaps // exactly. mHandler.postDelayed(new Runnable() { + @Override public void run() { animateCollapse(false); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index 0c8208f..a00fab3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -273,7 +273,8 @@ public class KeyButtonView extends ImageView { 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY, InputDevice.SOURCE_KEYBOARD); - InputManager.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); + InputManager.getInstance().injectInputEvent(ev, + InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java index f793af9..2171329 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java @@ -201,7 +201,6 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, if (closeKeyboard) { mImm.hideSoftInputFromWindow(getWindowToken(), 0); } - updateHardKeyboardEnabled(); } private void startActivity(Intent intent) { @@ -329,6 +328,7 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, mHardKeyboardSection.setVisibility(View.VISIBLE); if (mHardKeyboardSwitch.isChecked() != mHardKeyboardEnabled) { mHardKeyboardSwitch.setChecked(mHardKeyboardEnabled); + updateHardKeyboardEnabled(); } } else { mHardKeyboardSection.setVisibility(View.GONE); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index 09283f4..ba51108 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -867,9 +867,14 @@ public class TabletStatusBar extends BaseStatusBar implements } final StatusBarNotification oldNotification = oldEntry.notification; - final RemoteViews oldContentView = oldNotification.notification.contentView; - final RemoteViews contentView = notification.notification.contentView; + // XXX: modify when we do something more intelligent with the two content views + final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null) + ? oldNotification.notification.bigContentView + : oldNotification.notification.contentView; + final RemoteViews contentView = (notification.notification.bigContentView != null) + ? notification.notification.bigContentView + : notification.notification.contentView; if (DEBUG) { Slog.d(TAG, "old notification: when=" + oldNotification.notification.when diff --git a/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java new file mode 100644 index 0000000..d445d5c --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/BiometricSensorUnlock.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.policy.impl; + +import android.view.View; + +interface BiometricSensorUnlock { + // Returns 'true' if the biometric sensor is available and is selected by user. + public boolean installedAndSelected(); + + // Returns 'true' if the biometric sensor has started its unlock procedure but has not yet + // accepted or rejected the user. + public boolean isRunning(); + + // Show the interface, but don't start the unlock procedure. The interface should disappear + // after the specified timeout. If the timeout is 0, the interface shows until another event, + // such as calling hide(), causes it to disappear. + public void show(long timeoutMilliseconds); + + // Hide the interface, if any, exposing the lockscreen. + public void hide(); + + // Stop the unlock procedure if running. Returns 'true' if it was in fact running. + public boolean stop(); + + // Start the unlock procedure. Returns ‘false’ if it can’t be started or if the backup should + // be used. + public boolean start(boolean suppressBiometricUnlock); + + // Provide a view to work within. + public void initializeAreaView(View topView); + + // Clean up any resources used by the biometric unlock. + public void cleanUp(); + + // Returns the Device Policy Manager quality (e.g. PASSWORD_QUALITY_BIOMETRIC_WEAK). + public int getQuality(); +} diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/FaceUnlock.java new file mode 100644 index 0000000..7b0a086 --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/FaceUnlock.java @@ -0,0 +1,374 @@ +/* + * Copyright (C) 2011 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.internal.policy.impl; + +import com.android.internal.R; +import com.android.internal.policy.IFaceLockCallback; +import com.android.internal.policy.IFaceLockInterface; +import com.android.internal.widget.LockPatternUtils; + +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.telephony.TelephonyManager; +import android.util.Log; +import android.view.View; + +public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback { + + private static final boolean DEBUG = false; + private static final String TAG = "FULLockscreen"; + + private final Context mContext; + private final KeyguardUpdateMonitor mUpdateMonitor; + + private IFaceLockInterface mService; + private boolean mBoundToService = false; + private View mAreaView; + + private Handler mHandler; + private final int MSG_SHOW_AREA_VIEW = 0; + private final int MSG_HIDE_AREA_VIEW = 1; + + private boolean mServiceRunning = false; + private final Object mServiceRunningLock = new Object(); + + // Long enough to stay visible while the service starts + // Short enough to not have to wait long for backup if service fails to start or crashes + // The service can take a couple of seconds to start on the first try after boot + private final int VIEW_AREA_SERVICE_TIMEOUT = 3000; + + // So the user has a consistent amount of time when brought to the backup method from FaceLock + private final int BACKUP_LOCK_TIMEOUT = 5000; + + /** + * Used to lookup the state of the lock pattern + */ + private final LockPatternUtils mLockPatternUtils; + + KeyguardScreenCallback mKeyguardScreenCallback; + + public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor, + LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) { + mContext = context; + mUpdateMonitor = updateMonitor; + mLockPatternUtils = lockPatternUtils; + mKeyguardScreenCallback = keyguardScreenCallback; + mHandler = new Handler(this); + } + + // Indicates whether FaceLock is in use + public boolean installedAndSelected() { + return (mLockPatternUtils.usingBiometricWeak() && + mLockPatternUtils.isBiometricWeakInstalled()); + } + + public boolean isRunning() { + return mServiceRunning; + } + + // Shows the FaceLock area for a period of time + public void show(long timeoutMillis) { + showArea(); + if (timeoutMillis > 0) + mHandler.sendEmptyMessageDelayed(MSG_HIDE_AREA_VIEW, timeoutMillis); + } + + // Hides the FaceLock area immediately + public void hide() { + // Remove messages to prevent a delayed show message from undo-ing the hide + removeAreaDisplayMessages(); + mHandler.sendEmptyMessage(MSG_HIDE_AREA_VIEW); + } + + // Tells FaceLock to stop and then unbinds from the FaceLock service + public boolean stop() { + boolean wasRunning = false; + if (installedAndSelected()) { + stopUi(); + + if (mBoundToService) { + wasRunning = true; + if (DEBUG) Log.d(TAG, "before unbind from FaceLock service"); + if (mService != null) { + try { + mService.unregisterCallback(mFaceLockCallback); + } catch (RemoteException e) { + // Not much we can do + } + } + mContext.unbindService(mConnection); + if (DEBUG) Log.d(TAG, "after unbind from FaceLock service"); + mBoundToService = false; + } else { + // This is usually not an error when this happens. Sometimes we will tell it to + // unbind multiple times because it's called from both onWindowFocusChanged and + // onDetachedFromWindow. + if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound"); + } + } + + return wasRunning; + } + + /** + * When screen is turned on and focused, need to bind to FaceLock service if we are using + * FaceLock, but only if we're not dealing with a call + */ + public boolean start(boolean suppressBiometricUnlock) { + final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached(); + final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts(); + final boolean backupIsTimedOut = + (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT); + if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries); + if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE + && installedAndSelected() + && !suppressBiometricUnlock + && !tooManyFaceUnlockTries + && !backupIsTimedOut) { + bind(); + + // Show FaceLock area, but only for a little bit so lockpattern will become visible if + // FaceLock fails to start or crashes + show(VIEW_AREA_SERVICE_TIMEOUT); + + // When switching between portrait and landscape view while FaceLock is running, the + // screen will eventually go dark unless we poke the wakelock when FaceLock is + // restarted + mKeyguardScreenCallback.pokeWakelock(); + } else { + hide(); + return false; + } + + return true; + } + + // Takes care of FaceLock area when layout is created + public void initializeAreaView(View topView) { + if (installedAndSelected()) { + mAreaView = topView.findViewById(R.id.faceLockAreaView); + if (mAreaView == null) { + Log.e(TAG, "Layout does not have areaView and FaceLock is enabled"); + } + } else { + mAreaView = null; // Set to null if not using FaceLock + } + } + + public void cleanUp() { + if (mService != null) { + try { + mService.unregisterCallback(mFaceLockCallback); + } catch (RemoteException e) { + // Not much we can do + } + stopUi(); + mService = null; + } + } + + public int getQuality() { + return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK; + } + + // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops + // This needs to be done in a handler because the call could be coming from a callback from the + // FaceLock service that is in a thread that can't modify the UI + @Override + public boolean handleMessage(Message msg) { + switch (msg.what) { + case MSG_SHOW_AREA_VIEW: + if (mAreaView != null) { + mAreaView.setVisibility(View.VISIBLE); + } + break; + case MSG_HIDE_AREA_VIEW: + if (mAreaView != null) { + mAreaView.setVisibility(View.INVISIBLE); + } + break; + default: + Log.w(TAG, "Unhandled message"); + return false; + } + return true; + } + + // Removes show and hide messages from the message queue + private void removeAreaDisplayMessages() { + mHandler.removeMessages(MSG_SHOW_AREA_VIEW); + mHandler.removeMessages(MSG_HIDE_AREA_VIEW); + } + + // Shows the FaceLock area immediately + private void showArea() { + // Remove messages to prevent a delayed hide message from undo-ing the show + removeAreaDisplayMessages(); + mHandler.sendEmptyMessage(MSG_SHOW_AREA_VIEW); + } + + // Binds to FaceLock service. This call does not tell it to start, but it causes the service + // to call the onServiceConnected callback, which then starts FaceLock. + private void bind() { + if (installedAndSelected()) { + if (!mBoundToService) { + if (DEBUG) Log.d(TAG, "before bind to FaceLock service"); + mContext.bindService(new Intent(IFaceLockInterface.class.getName()), + mConnection, + Context.BIND_AUTO_CREATE, + mLockPatternUtils.getCurrentUser()); + if (DEBUG) Log.d(TAG, "after bind to FaceLock service"); + mBoundToService = true; + } else { + Log.w(TAG, "Attempt to bind to FaceLock when already bound"); + } + } + } + + private ServiceConnection mConnection = new ServiceConnection() { + // Completes connection, registers callback and starts FaceLock when service is bound + @Override + public void onServiceConnected(ComponentName className, IBinder iservice) { + mService = IFaceLockInterface.Stub.asInterface(iservice); + if (DEBUG) Log.d(TAG, "Connected to FaceLock service"); + try { + mService.registerCallback(mFaceLockCallback); + } catch (RemoteException e) { + Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString()); + mService = null; + mBoundToService = false; + return; + } + + if (mAreaView != null) { + int[] position; + position = new int[2]; + mAreaView.getLocationInWindow(position); + startUi(mAreaView.getWindowToken(), position[0], position[1], + mAreaView.getWidth(), mAreaView.getHeight()); + } + } + + // Cleans up if FaceLock service unexpectedly disconnects + @Override + public void onServiceDisconnected(ComponentName className) { + synchronized(mServiceRunningLock) { + mService = null; + mServiceRunning = false; + } + mBoundToService = false; + Log.w(TAG, "Unexpected disconnect from FaceLock service"); + } + }; + + // Tells the FaceLock service to start displaying its UI and perform recognition + private void startUi(IBinder windowToken, int x, int y, int w, int h) { + if (installedAndSelected()) { + synchronized (mServiceRunningLock) { + if (!mServiceRunning) { + if (DEBUG) Log.d(TAG, "Starting FaceLock"); + try { + mService.startUi(windowToken, x, y, w, h, + mLockPatternUtils.isBiometricWeakLivelinessEnabled()); + } catch (RemoteException e) { + Log.e(TAG, "Caught exception starting FaceLock: " + e.toString()); + return; + } + mServiceRunning = true; + } else { + if (DEBUG) Log.w(TAG, "startUi() attempted while running"); + } + } + } + } + + // Tells the FaceLock service to stop displaying its UI and stop recognition + private void stopUi() { + if (installedAndSelected()) { + // Note that attempting to stop FaceLock when it's not running is not an issue. + // FaceLock can return, which stops it and then we try to stop it when the + // screen is turned off. That's why we check. + synchronized (mServiceRunningLock) { + if (mServiceRunning) { + try { + if (DEBUG) Log.d(TAG, "Stopping FaceLock"); + mService.stopUi(); + } catch (RemoteException e) { + Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString()); + } + mServiceRunning = false; + } + } + } + } + + // Implements the FaceLock service callback interface defined in AIDL + private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() { + // Stops the FaceLock UI and indicates that the phone should be unlocked + @Override + public void unlock() { + if (DEBUG) Log.d(TAG, "FaceLock unlock()"); + showArea(); // Keep fallback covered + stop(); + + mKeyguardScreenCallback.keyguardDone(true); + mKeyguardScreenCallback.reportSuccessfulUnlockAttempt(); + } + + // Stops the FaceLock UI and exposes the backup method without unlocking + // This means the user has cancelled out + @Override + public void cancel() { + if (DEBUG) Log.d(TAG, "FaceLock cancel()"); + hide(); // Expose fallback + stop(); + mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); + } + + // Stops the FaceLock UI and exposes the backup method without unlocking + // This means FaceLock failed to recognize them + @Override + public void reportFailedAttempt() { + if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()"); + mUpdateMonitor.reportFailedFaceUnlockAttempt(); + hide(); // Expose fallback + stop(); + mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); + } + + // Removes the black area that covers the backup unlock method + @Override + public void exposeFallback() { + if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()"); + hide(); // Expose fallback + } + + // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive + @Override + public void pokeWakelock() { + if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()"); + mKeyguardScreenCallback.pokeWakelock(); + } + }; +} diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 52fb875..5b9160d 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -567,6 +567,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, synchronized (KeyguardViewMediator.this) { if (mHidden != isHidden) { mHidden = isHidden; + updateActivityLockScreenState(); adjustUserActivityLocked(); adjustStatusBarLocked(); } @@ -1162,6 +1163,14 @@ public class KeyguardViewMediator implements KeyguardViewCallback, } } + private void updateActivityLockScreenState() { + try { + ActivityManagerNative.getDefault().setLockScreenShown( + mShowing && !mHidden); + } catch (RemoteException e) { + } + } + /** * Handle message sent by {@link #showLocked}. * @see #SHOW @@ -1173,6 +1182,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, mKeyguardViewManager.show(); mShowing = true; + updateActivityLockScreenState(); adjustUserActivityLocked(); adjustStatusBarLocked(); try { @@ -1207,6 +1217,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, mKeyguardViewManager.hide(); mShowing = false; + updateActivityLockScreenState(); adjustUserActivityLocked(); adjustStatusBarLocked(); } @@ -1324,6 +1335,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback, if (DEBUG) Log.d(TAG, "handleVerifyUnlock"); mKeyguardViewManager.verifyUnlock(); mShowing = true; + updateActivityLockScreenState(); } } diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 404dc6f..c382646 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -20,8 +20,6 @@ import com.android.internal.R; import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallback; import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl; import com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode; -import com.android.internal.policy.IFaceLockCallback; -import com.android.internal.policy.IFaceLockInterface; import com.android.internal.telephony.IccCard; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockScreenWidgetCallback; @@ -36,12 +34,10 @@ import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.app.AlertDialog; import android.app.admin.DevicePolicyManager; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; -import android.content.ServiceConnection; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -50,12 +46,8 @@ import android.graphics.PixelFormat; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.IBinder; import android.os.Parcelable; import android.os.PowerManager; -import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.telephony.TelephonyManager; @@ -82,7 +74,7 @@ import java.io.IOException; * {@link com.android.internal.policy.impl.KeyguardViewManager} * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate. */ -public class LockPatternKeyguardView extends KeyguardViewBase implements Handler.Callback { +public class LockPatternKeyguardView extends KeyguardViewBase { private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000; @@ -109,36 +101,17 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler private boolean mShowLockBeforeUnlock = false; - // The following were added to support FaceLock - private IFaceLockInterface mFaceLockService; - private boolean mBoundToFaceLockService = false; - private View mFaceLockAreaView; - - private boolean mFaceLockServiceRunning = false; - private final Object mFaceLockServiceRunningLock = new Object(); - private final Object mFaceLockStartupLock = new Object(); - - private Handler mHandler; - private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0; - private final int MSG_HIDE_FACELOCK_AREA_VIEW = 1; - + // Interface to a biometric sensor that can optionally be used to unlock the device + private BiometricSensorUnlock mBiometricUnlock; + private final Object mBiometricUnlockStartupLock = new Object(); // Long enough to stay visible while dialer comes up // Short enough to not be visible if the user goes back immediately - private final int FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT = 1000; - - // Long enough to stay visible while the service starts - // Short enough to not have to wait long for backup if service fails to start or crashes - // The service can take a couple of seconds to start on the first try after boot - private final int FACELOCK_VIEW_AREA_SERVICE_TIMEOUT = 3000; - - // So the user has a consistent amount of time when brought to the backup method from FaceLock - private final int BACKUP_LOCK_TIMEOUT = 5000; + private final int BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT = 1000; private boolean mRequiresSim; - //True if we have some sort of overlay on top of the Lockscreen - //Also true if we've activated a phone call, either emergency dialing or incoming - //This resets when the phone is turned off with no current call - private boolean mHasOverlay; + // True if the biometric unlock should not be displayed. For example, if there is an overlay on + // lockscreen or the user is plugging in / unplugging the device. + private boolean mSupressBiometricUnlock; //True if a dialog is currently displaying on top of this window //Unlike other overlays, this does not close with a power button cycle private boolean mHasDialog = false; @@ -337,15 +310,15 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } public void takeEmergencyCallAction() { - mHasOverlay = true; + mSupressBiometricUnlock = true; - // Continue showing FaceLock area until dialer comes up or call is resumed - if (usingFaceLock() && mFaceLockServiceRunning) { - showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT); + if (mBiometricUnlock.installedAndSelected() && mBiometricUnlock.isRunning()) { + // Continue covering backup lock until dialer comes up or call is resumed + mBiometricUnlock.show(BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT); } - // FaceLock must be stopped if it is running when emergency call is pressed - stopAndUnbindFromFaceLock(); + // The biometric unlock must be stopped if it is running when emergency call is pressed + mBiometricUnlock.stop(); pokeWakelock(EMERGENCY_CALL_TIMEOUT); if (TelephonyManager.getDefault().getCallState() @@ -450,14 +423,15 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler LockPatternUtils lockPatternUtils, KeyguardWindowController controller) { super(context, callback); - mHandler = new Handler(this); + mBiometricUnlock = new FaceUnlock(context, updateMonitor, lockPatternUtils, + mKeyguardScreenCallback); mConfiguration = context.getResources().getConfiguration(); mEnableFallback = false; mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim")); mUpdateMonitor = updateMonitor; mLockPatternUtils = lockPatternUtils; mWindowController = controller; - mHasOverlay = false; + mSupressBiometricUnlock = false; mPluggedIn = mUpdateMonitor.isDevicePluggedIn(); mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn(); @@ -556,8 +530,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler if (DEBUG) Log.d(TAG, "screen off"); mScreenOn = false; mForgotPattern = false; - mHasOverlay = mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE || - mHasDialog; + mSupressBiometricUnlock = + mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE || mHasDialog; // Emulate activity life-cycle for both lock and unlock screen. if (mLockScreen != null) { @@ -569,54 +543,25 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler saveWidgetState(); - // When screen is turned off, need to unbind from FaceLock service if using FaceLock - stopAndUnbindFromFaceLock(); - } - - /** When screen is turned on and focused, need to bind to FaceLock service if we are using - * FaceLock, but only if we're not dealing with a call - */ - private void activateFaceLockIfAble() { - final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached(); - final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts(); - final boolean backupIsTimedOut = - (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT); - if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries); - if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE - && usingFaceLock() - && !mHasOverlay - && !tooManyFaceUnlockTries - && !backupIsTimedOut) { - bindToFaceLock(); - - // Show FaceLock area, but only for a little bit so lockpattern will become visible if - // FaceLock fails to start or crashes - showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT); - - // When switching between portrait and landscape view while FaceLock is running, the - // screen will eventually go dark unless we poke the wakelock when FaceLock is - // restarted - mKeyguardScreenCallback.pokeWakelock(); - } else { - hideFaceLockArea(); - } + // The biometric unlock must stop when screen turns off. + mBiometricUnlock.stop(); } @Override public void onScreenTurnedOn() { if (DEBUG) Log.d(TAG, "screen on"); - boolean runFaceLock = false; - //Make sure to start facelock iff the screen is both on and focused - synchronized(mFaceLockStartupLock) { + boolean startBiometricUnlock = false; + // Start the biometric unlock if and only if the screen is both on and focused + synchronized(mBiometricUnlockStartupLock) { mScreenOn = true; - runFaceLock = mWindowFocused; + startBiometricUnlock = mWindowFocused; } show(); restoreWidgetState(); - if (runFaceLock) activateFaceLockIfAble(); + if (startBiometricUnlock) mBiometricUnlock.start(mSupressBiometricUnlock); } private void saveWidgetState() { @@ -635,25 +580,26 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } } - /** Unbind from facelock if something covers this window (such as an alarm) - * bind to facelock if the lockscreen window just came into focus, and the screen is on + /** + * Stop the biometric unlock if something covers this window (such as an alarm) + * Start the biometric unlock if the lockscreen window just came into focus and the screen is on */ @Override public void onWindowFocusChanged (boolean hasWindowFocus) { if (DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused"); - boolean runFaceLock = false; - //Make sure to start facelock iff the screen is both on and focused - synchronized(mFaceLockStartupLock) { - if(mScreenOn && !mWindowFocused) runFaceLock = hasWindowFocus; + boolean startBiometricUnlock = false; + // Start the biometric unlock if and only if the screen is both on and focused + synchronized(mBiometricUnlockStartupLock) { + if (mScreenOn && !mWindowFocused) startBiometricUnlock = hasWindowFocus; mWindowFocused = hasWindowFocus; } - if(!hasWindowFocus) { - mHasOverlay = true; - stopAndUnbindFromFaceLock(); - hideFaceLockArea(); + if (!hasWindowFocus) { + mSupressBiometricUnlock = true; + mBiometricUnlock.stop(); + mBiometricUnlock.hide(); } else { mHasDialog = false; - if (runFaceLock) activateFaceLockIfAble(); + if (startBiometricUnlock) mBiometricUnlock.start(mSupressBiometricUnlock); } } @@ -667,14 +613,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler ((KeyguardScreen) mUnlockScreen).onResume(); } - if (usingFaceLock() && !mHasOverlay) { + if (mBiometricUnlock.installedAndSelected() && !mSupressBiometricUnlock) { // Note that show() gets called before the screen turns off to set it up for next time - // it is turned on. We don't want to set a timeout on the FaceLock area here because it - // may be gone by the time the screen is turned on again. We set the timeout when the - // screen turns on instead. - showFaceLockArea(); + // it is turned on. We don't want to set a timeout on the biometric unlock here because + // it may be gone by the time the screen is turned on again. We set the timeout when + // the screen turns on instead. + mBiometricUnlock.show(0); } else { - hideFaceLockArea(); + mBiometricUnlock.hide(); } } @@ -708,9 +654,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler removeCallbacks(mRecreateRunnable); - // When view is hidden, need to unbind from FaceLock service if we are using FaceLock + // When view is hidden, we need to stop the biometric unlock // e.g., when device becomes unlocked - stopAndUnbindFromFaceLock(); + mBiometricUnlock.stop(); super.onDetachedFromWindow(); } @@ -727,16 +673,19 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() { - /** When somebody plugs in or unplugs the device, we don't want to display faceunlock */ + /** + * When somebody plugs in or unplugs the device, we don't want to display the biometric + * unlock. + */ @Override public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { - mHasOverlay |= mPluggedIn != pluggedIn; + mSupressBiometricUnlock |= mPluggedIn != pluggedIn; mPluggedIn = pluggedIn; - //If it's already running, don't close it down: the unplug didn't start it - if (!mFaceLockServiceRunning) { - stopAndUnbindFromFaceLock(); - hideFaceLockArea(); + // If it's already running, don't close it down: the unplug didn't start it + if (!mBiometricUnlock.isRunning()) { + mBiometricUnlock.stop(); + mBiometricUnlock.hide(); } } @@ -747,19 +696,20 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler | (mUpdateMonitor.isClockVisible() ? View.STATUS_BAR_DISABLE_CLOCK : 0)); } - //We need to stop faceunlock when a phonecall comes in + // We need to stop the biometric unlock when a phone call comes in @Override public void onPhoneStateChanged(int phoneState) { if (DEBUG) Log.d(TAG, "phone state: " + phoneState); if(phoneState == TelephonyManager.CALL_STATE_RINGING) { - mHasOverlay = true; - stopAndUnbindFromFaceLock(); - hideFaceLockArea(); + mSupressBiometricUnlock = true; + mBiometricUnlock.stop(); + mBiometricUnlock.hide(); } } @Override public void onUserChanged(int userId) { + mBiometricUnlock.stop(); mLockPatternUtils.setCurrentUser(userId); updateScreen(getInitialMode(), true); } @@ -822,15 +772,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler mUnlockScreen = null; } mUpdateMonitor.removeCallback(this); - if (mFaceLockService != null) { - try { - mFaceLockService.unregisterCallback(mFaceLockCallback); - } catch (RemoteException e) { - // Not much we can do - } - stopFaceLock(); - mFaceLockService = null; - } + mBiometricUnlock.cleanUp(); } private boolean isSecure() { @@ -880,9 +822,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler final UnlockMode unlockMode = getUnlockMode(); if (mode == Mode.UnlockScreen && unlockMode != UnlockMode.Unknown) { if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) { - boolean restartFaceLock = stopFaceLockIfRunning(); + boolean restartBiometricUnlock = mBiometricUnlock.stop(); recreateUnlockScreen(unlockMode); - if (restartFaceLock) activateFaceLockIfAble(); + if (restartBiometricUnlock) { + mBiometricUnlock.start(mSupressBiometricUnlock); + } } } @@ -995,7 +939,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler throw new IllegalArgumentException("unknown unlock mode " + unlockMode); } initializeTransportControlView(unlockView); - initializeFaceLockAreaView(unlockView); // Only shows view if FaceLock is enabled + // Only shows view if the biometric unlock is enabled + mBiometricUnlock.initializeAreaView(unlockView); mUnlockScreenMode = unlockMode; return unlockView; @@ -1177,254 +1122,4 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler return mBitmap.getHeight(); } } - - // Everything below pertains to FaceLock - might want to separate this out - - // Indicates whether FaceLock is in use - private boolean usingFaceLock() { - return (mLockPatternUtils.usingBiometricWeak() && - mLockPatternUtils.isBiometricWeakInstalled()); - } - - // Takes care of FaceLock area when layout is created - private void initializeFaceLockAreaView(View view) { - if (usingFaceLock()) { - mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView); - if (mFaceLockAreaView == null) { - Log.e(TAG, "Layout does not have faceLockAreaView and FaceLock is enabled"); - } - } else { - mFaceLockAreaView = null; // Set to null if not using FaceLock - } - } - - // Stops FaceLock if it is running and reports back whether it was running or not - private boolean stopFaceLockIfRunning() { - if (usingFaceLock() && mBoundToFaceLockService) { - stopAndUnbindFromFaceLock(); - return true; - } - return false; - } - - // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops - // This needs to be done in a handler because the call could be coming from a callback from the - // FaceLock service that is in a thread that can't modify the UI - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case MSG_SHOW_FACELOCK_AREA_VIEW: - if (mFaceLockAreaView != null) { - mFaceLockAreaView.setVisibility(View.VISIBLE); - } - break; - case MSG_HIDE_FACELOCK_AREA_VIEW: - if (mFaceLockAreaView != null) { - mFaceLockAreaView.setVisibility(View.INVISIBLE); - } - break; - default: - Log.w(TAG, "Unhandled message"); - return false; - } - return true; - } - - // Removes show and hide messages from the message queue - private void removeFaceLockAreaDisplayMessages() { - mHandler.removeMessages(MSG_SHOW_FACELOCK_AREA_VIEW); - mHandler.removeMessages(MSG_HIDE_FACELOCK_AREA_VIEW); - } - - // Shows the FaceLock area immediately - private void showFaceLockArea() { - // Remove messages to prevent a delayed hide message from undo-ing the show - removeFaceLockAreaDisplayMessages(); - mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); - } - - // Hides the FaceLock area immediately - private void hideFaceLockArea() { - // Remove messages to prevent a delayed show message from undo-ing the hide - removeFaceLockAreaDisplayMessages(); - mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); - } - - // Shows the FaceLock area for a period of time - private void showFaceLockAreaWithTimeout(long timeoutMillis) { - showFaceLockArea(); - mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, timeoutMillis); - } - - // Binds to FaceLock service. This call does not tell it to start, but it causes the service - // to call the onServiceConnected callback, which then starts FaceLock. - public void bindToFaceLock() { - if (usingFaceLock()) { - if (!mBoundToFaceLockService) { - if (DEBUG) Log.d(TAG, "before bind to FaceLock service"); - mContext.bindService(new Intent(IFaceLockInterface.class.getName()), - mFaceLockConnection, - Context.BIND_AUTO_CREATE); - if (DEBUG) Log.d(TAG, "after bind to FaceLock service"); - mBoundToFaceLockService = true; - } else { - Log.w(TAG, "Attempt to bind to FaceLock when already bound"); - } - } - } - - // Tells FaceLock to stop and then unbinds from the FaceLock service - public void stopAndUnbindFromFaceLock() { - if (usingFaceLock()) { - stopFaceLock(); - - if (mBoundToFaceLockService) { - if (DEBUG) Log.d(TAG, "before unbind from FaceLock service"); - if (mFaceLockService != null) { - try { - mFaceLockService.unregisterCallback(mFaceLockCallback); - } catch (RemoteException e) { - // Not much we can do - } - } - mContext.unbindService(mFaceLockConnection); - if (DEBUG) Log.d(TAG, "after unbind from FaceLock service"); - mBoundToFaceLockService = false; - } else { - // This is usually not an error when this happens. Sometimes we will tell it to - // unbind multiple times because it's called from both onWindowFocusChanged and - // onDetachedFromWindow. - if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound"); - } - } - } - - private ServiceConnection mFaceLockConnection = new ServiceConnection() { - // Completes connection, registers callback and starts FaceLock when service is bound - @Override - public void onServiceConnected(ComponentName className, IBinder iservice) { - mFaceLockService = IFaceLockInterface.Stub.asInterface(iservice); - if (DEBUG) Log.d(TAG, "Connected to FaceLock service"); - try { - mFaceLockService.registerCallback(mFaceLockCallback); - } catch (RemoteException e) { - Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString()); - mFaceLockService = null; - mBoundToFaceLockService = false; - return; - } - - if (mFaceLockAreaView != null) { - int[] faceLockPosition; - faceLockPosition = new int[2]; - mFaceLockAreaView.getLocationInWindow(faceLockPosition); - startFaceLock(mFaceLockAreaView.getWindowToken(), - faceLockPosition[0], faceLockPosition[1], - mFaceLockAreaView.getWidth(), mFaceLockAreaView.getHeight()); - } - } - - // Cleans up if FaceLock service unexpectedly disconnects - @Override - public void onServiceDisconnected(ComponentName className) { - synchronized(mFaceLockServiceRunningLock) { - mFaceLockService = null; - mFaceLockServiceRunning = false; - } - mBoundToFaceLockService = false; - Log.w(TAG, "Unexpected disconnect from FaceLock service"); - } - }; - - // Tells the FaceLock service to start displaying its UI and perform recognition - public void startFaceLock(IBinder windowToken, int x, int y, int w, int h) - { - if (usingFaceLock()) { - synchronized (mFaceLockServiceRunningLock) { - if (!mFaceLockServiceRunning) { - if (DEBUG) Log.d(TAG, "Starting FaceLock"); - try { - mFaceLockService.startUi(windowToken, x, y, w, h); - } catch (RemoteException e) { - Log.e(TAG, "Caught exception starting FaceLock: " + e.toString()); - return; - } - mFaceLockServiceRunning = true; - } else { - if (DEBUG) Log.w(TAG, "startFaceLock() attempted while running"); - } - } - } - } - - // Tells the FaceLock service to stop displaying its UI and stop recognition - public void stopFaceLock() - { - if (usingFaceLock()) { - // Note that attempting to stop FaceLock when it's not running is not an issue. - // FaceLock can return, which stops it and then we try to stop it when the - // screen is turned off. That's why we check. - synchronized (mFaceLockServiceRunningLock) { - if (mFaceLockServiceRunning) { - try { - if (DEBUG) Log.d(TAG, "Stopping FaceLock"); - mFaceLockService.stopUi(); - } catch (RemoteException e) { - Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString()); - } - mFaceLockServiceRunning = false; - } - } - } - } - - // Implements the FaceLock service callback interface defined in AIDL - private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() { - - // Stops the FaceLock UI and indicates that the phone should be unlocked - @Override - public void unlock() { - if (DEBUG) Log.d(TAG, "FaceLock unlock()"); - showFaceLockArea(); // Keep fallback covered - stopAndUnbindFromFaceLock(); - - mKeyguardScreenCallback.keyguardDone(true); - mKeyguardScreenCallback.reportSuccessfulUnlockAttempt(); - } - - // Stops the FaceLock UI and exposes the backup method without unlocking - // This means the user has cancelled out - @Override - public void cancel() { - if (DEBUG) Log.d(TAG, "FaceLock cancel()"); - hideFaceLockArea(); // Expose fallback - stopAndUnbindFromFaceLock(); - mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); - } - - // Stops the FaceLock UI and exposes the backup method without unlocking - // This means FaceLock failed to recognize them - @Override - public void reportFailedAttempt() { - if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()"); - mUpdateMonitor.reportFailedFaceUnlockAttempt(); - hideFaceLockArea(); // Expose fallback - stopAndUnbindFromFaceLock(); - mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT); - } - - // Removes the black area that covers the backup unlock method - @Override - public void exposeFallback() { - if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()"); - hideFaceLockArea(); // Expose fallback - } - - // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive - @Override - public void pokeWakelock() { - if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()"); - mKeyguardScreenCallback.pokeWakelock(); - } - }; } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 5697284..0a63840 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -65,6 +65,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.telephony.ITelephony; import com.android.internal.widget.PointerLocationView; +import android.service.dreams.IDreamManager; import android.speech.RecognizerIntent; import android.util.DisplayMetrics; import android.util.EventLog; @@ -108,6 +109,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_DRAG; +import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; @@ -202,26 +204,28 @@ public class PhoneWindowManager implements WindowManagerPolicy { // responsible for power management when displayed. static final int KEYGUARD_LAYER = 11; static final int KEYGUARD_DIALOG_LAYER = 12; - static final int STATUS_BAR_SUB_PANEL_LAYER = 13; - static final int STATUS_BAR_LAYER = 14; - static final int STATUS_BAR_PANEL_LAYER = 15; + // used for Dreams (screensavers with TYPE_DREAM windows) + static final int SCREENSAVER_LAYER = 13; + static final int STATUS_BAR_SUB_PANEL_LAYER = 14; + static final int STATUS_BAR_LAYER = 15; + static final int STATUS_BAR_PANEL_LAYER = 16; // the on-screen volume indicator and controller shown when the user // changes the device volume - static final int VOLUME_OVERLAY_LAYER = 16; + static final int VOLUME_OVERLAY_LAYER = 17; // things in here CAN NOT take focus, but are shown on top of everything else. - static final int SYSTEM_OVERLAY_LAYER = 17; + static final int SYSTEM_OVERLAY_LAYER = 18; // the navigation bar, if available, shows atop most things - static final int NAVIGATION_BAR_LAYER = 18; + static final int NAVIGATION_BAR_LAYER = 19; // system-level error dialogs - static final int SYSTEM_ERROR_LAYER = 19; + static final int SYSTEM_ERROR_LAYER = 20; // the drag layer: input for drag-and-drop is associated with this window, // which sits above all other focusable windows - static final int DRAG_LAYER = 20; - static final int SECURE_SYSTEM_OVERLAY_LAYER = 21; - static final int BOOT_PROGRESS_LAYER = 22; + static final int DRAG_LAYER = 21; + static final int SECURE_SYSTEM_OVERLAY_LAYER = 22; + static final int BOOT_PROGRESS_LAYER = 23; // the (mouse) pointer layer - static final int POINTER_LAYER = 23; - static final int HIDDEN_NAV_CONSUMER_LAYER = 24; + static final int POINTER_LAYER = 24; + static final int HIDDEN_NAV_CONSUMER_LAYER = 25; static final int APPLICATION_MEDIA_SUBLAYER = -2; static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; @@ -323,7 +327,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { RecentApplicationsDialog mRecentAppsDialog; int mRecentAppsDialogHeldModifiers; - int mLidOpen = LID_ABSENT; + int mLidState = LID_ABSENT; boolean mSystemReady; boolean mSystemBooted; @@ -453,6 +457,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mLockScreenTimerActive; // visual screen saver support + boolean mScreenSaverFeatureAvailable; int mScreenSaverTimeout = 0; boolean mScreenSaverEnabledByUser = false; boolean mScreenSaverMayRun = true; // false if a wakelock is held @@ -1076,6 +1081,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateRotation = true; } + // dreams + mScreenSaverFeatureAvailable = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_enableDreams); + mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver, Settings.Secure.SCREENSAVER_ENABLED, 1); @@ -1091,7 +1100,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mScreenSaverTimeout -= 5000; } } - updateScreenSaverTimeoutLocked(); } if (updateRotation) { updateRotation(true); @@ -1179,6 +1187,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // this... should introduce a token to let the system // monitor/control what they are doing. break; + case TYPE_DREAM: case TYPE_INPUT_METHOD: case TYPE_WALLPAPER: // The window manager will check these. @@ -1216,16 +1225,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { } void readLidState() { - mLidOpen = mWindowManagerFuncs.getLidState(); + mLidState = mWindowManagerFuncs.getLidState(); } private int determineHiddenState(int mode, int hiddenValue, int visibleValue) { - if (mLidOpen != LID_ABSENT) { + if (mLidState != LID_ABSENT) { switch (mode) { case 1: - return mLidOpen == LID_OPEN ? visibleValue : hiddenValue; + return mLidState == LID_OPEN ? visibleValue : hiddenValue; case 2: - return mLidOpen == LID_OPEN ? hiddenValue : visibleValue; + return mLidState == LID_OPEN ? hiddenValue : visibleValue; } } return visibleValue; @@ -1309,6 +1318,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { return BOOT_PROGRESS_LAYER; case TYPE_HIDDEN_NAV_CONSUMER: return HIDDEN_NAV_CONSUMER_LAYER; + case TYPE_DREAM: + return SCREENSAVER_LAYER; } Log.e(TAG, "Unknown window type: " + type); return APPLICATION_LAYER; @@ -1340,18 +1351,29 @@ public class PhoneWindowManager implements WindowManagerPolicy { } public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) { - // Assumes that the navigation bar appears on the side of the display in landscape. - if (mHasNavigationBar && fullWidth > fullHeight) { - return fullWidth - mNavigationBarWidth; + if (mHasNavigationBar) { + // For a basic navigation bar, when we are in landscape mode we place + // the navigation bar to the side. + if (fullWidth > fullHeight) { + return fullWidth - mNavigationBarWidth; + } } return fullWidth; } public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) { - // Assumes the navigation bar appears on the bottom of the display in portrait. - return fullHeight - - (mHasSystemNavBar ? mNavigationBarHeight : 0) - - ((mHasNavigationBar && fullWidth > fullHeight) ? 0 : mNavigationBarHeight); + if (mHasSystemNavBar) { + // For the system navigation bar, we always place it at the bottom. + return fullHeight - mNavigationBarHeight; + } + if (mHasNavigationBar) { + // For a basic navigation bar, when we are in portrait mode we place + // the navigation bar to the bottom. + if (fullWidth < fullHeight) { + return fullHeight - mNavigationBarHeight; + } + } + return fullHeight; } public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) { @@ -1359,13 +1381,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) { - // This is the same as getNonDecorDisplayHeight, unless the status bar - // can hide. If the status bar can hide, we don't count that as part - // of the decor; however for purposes of configurations, we do want to - // exclude it since applications can't generally use that part of the - // screen. - return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - - (mHasSystemNavBar ? 0 : mStatusBarHeight); + // If we don't have a system nav bar, then there is a separate status + // bar at the top of the display. We don't count that as part of the + // fixed decor, since it can hide; however, for purposes of configurations, + // we do want to exclude it since applications can't generally use that part + // of the screen. + if (!mHasSystemNavBar) { + return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - mStatusBarHeight; + } + return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation); } public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) { @@ -1604,9 +1628,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 0; } - public Animation createForceHideEnterAnimation() { - return AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.lock_screen_behind_enter); + public Animation createForceHideEnterAnimation(boolean onWallpaper) { + return AnimationUtils.loadAnimation(mContext, onWallpaper + ? com.android.internal.R.anim.lock_screen_wallpaper_behind_enter + : com.android.internal.R.anim.lock_screen_behind_enter); } static ITelephony getTelephonyService() { @@ -2221,12 +2246,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { vf.right = mStableRight; vf.bottom = mStableBottom; + // Let the status bar determine its size. mStatusBar.computeFrameLw(pf, df, vf, vf); - final Rect r = mStatusBar.getFrameLw(); - // Compute the stable dimensions whether or not the status bar is hidden. - if (mDockTop == r.top) mStableTop = r.bottom; - else if (mDockBottom == r.bottom) mStableBottom = r.top; + // For layout, the status bar is always at the top with our fixed height. + mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; // If the status bar is hidden, we don't want to cause // windows behind it to scroll. @@ -2234,8 +2258,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Status bar may go away, so the screen area it occupies // is available to apps but just covering them when the // status bar is visible. - if (mDockTop == r.top) mDockTop = r.bottom; - else if (mDockBottom == r.bottom) mDockBottom = r.top; + mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; mContentTop = mCurTop = mDockTop; mContentBottom = mCurBottom = mDockBottom; @@ -2773,7 +2796,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mHeadless) return; // lid changed state - mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED; + mLidState = lidOpen ? LID_OPEN : LID_CLOSED; updateKeyboardVisibility(); boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen); @@ -3317,7 +3340,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { synchronized (mLock) { updateOrientationListenerLp(); updateLockScreenTimeout(); - updateScreenSaverTimeoutLocked(); } } @@ -3366,7 +3388,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mScreenOnEarly = true; updateOrientationListenerLp(); updateLockScreenTimeout(); - updateScreenSaverTimeoutLocked(); } } @@ -3464,7 +3485,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } final int preferredRotation; - if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) { + if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { // Ignore sensor when lid switch is open and rotation is forced. preferredRotation = mLidOpenRotation; } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR @@ -3756,83 +3777,58 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); } } + } - synchronized (mLock) { - // Only posts messages; holds no additional locks. - updateScreenSaverTimeoutLocked(); + private IDreamManager getDreamManager() { + if (!mScreenSaverFeatureAvailable) { + return null; } + + IDreamManager sandman = IDreamManager.Stub.asInterface( + ServiceManager.checkService("dreams")); + if (sandman == null) { + Log.w(TAG, "Unable to find IDreamManager"); + } + return sandman; } - Runnable mScreenSaverActivator = new Runnable() { - public void run() { - if (!(mScreenSaverMayRun && mScreenOnEarly)) { - Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?"); - return; - } - if (!mPluggedIn) { - if (localLOGV) Log.v(TAG, "mScreenSaverActivator: not running screen saver when not plugged in"); - return; - } - // Quick fix for automation tests. - // The correct fix is to move this triggering logic to PowerManager, where more complete - // information about wakelocks (including StayOnWhilePluggedIn) is available. - if (Settings.System.getInt(mContext.getContentResolver(), - Settings.System.STAY_ON_WHILE_PLUGGED_IN, - BatteryManager.BATTERY_PLUGGED_AC) != 0) { - Log.v(TAG, "mScreenSaverActivator: not running screen saver when STAY_ON_WHILE_PLUGGED_IN"); - return; - } + @Override + public boolean isScreenSaverEnabled() { + return (mScreenSaverFeatureAvailable && mScreenSaverEnabledByUser + && mScreenSaverMayRun && mScreenOnEarly && mPluggedIn); + } - if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland"); + @Override + public boolean startScreenSaver() { + synchronized (mLock) { + if (isScreenSaverEnabled()) { + IDreamManager dm = getDreamManager(); + if (dm == null) return false; + + try { + if (localLOGV) Log.v(TAG, "startScreenSaver: entering dreamland..."); - try { - String component = Settings.Secure.getString( - mContext.getContentResolver(), Settings.Secure.SCREENSAVER_COMPONENT); - if (component == null) { - component = mContext.getResources().getString(R.string.config_defaultDreamComponent); + dm.dream(); + return true; + } catch (RemoteException ex) { + // too bad, so sad, oh mom, oh dad } - if (component != null) { - // dismiss the notification shade, recents, etc. - mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) - .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)); - - ComponentName cn = ComponentName.unflattenFromString(component); - Intent intent = new Intent(Intent.ACTION_MAIN) - .setComponent(cn) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - | Intent.FLAG_ACTIVITY_NO_USER_ACTION - | Intent.FLAG_FROM_BACKGROUND - | Intent.FLAG_ACTIVITY_NO_HISTORY - ); - mContext.startActivity(intent); - } else { - Log.e(TAG, "Couldn't start screen saver: none selected"); - } - } catch (android.content.ActivityNotFoundException exc) { - // no screensaver? give up - Log.e(TAG, "Couldn't start screen saver: none installed"); } } - }; - - // Must call while holding mLock - private void updateScreenSaverTimeoutLocked() { - if (mScreenSaverActivator == null) return; + return false; + } - mHandler.removeCallbacks(mScreenSaverActivator); - if (mScreenSaverEnabledByUser && mScreenSaverMayRun && mScreenOnEarly && mScreenSaverTimeout > 0) { - if (localLOGV) - Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now"); - mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout); - } else { - if (localLOGV) { - if (!mScreenSaverEnabledByUser || mScreenSaverTimeout == 0) - Log.v(TAG, "screen saver disabled by user"); - else if (!mScreenOnEarly) - Log.v(TAG, "screen saver disabled while screen off"); - else - Log.v(TAG, "screen saver disabled by wakelock"); + @Override + public void stopScreenSaver() { + synchronized (mLock) { + IDreamManager dm = getDreamManager(); + if (dm == null) return; + + try { + if (localLOGV) Log.v(TAG, "startScreenSaver: awakening..."); + + dm.awaken(); + } catch (RemoteException ex) { } } } @@ -3881,7 +3877,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void updateKeyboardVisibility() { - mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN); + mPowerManager.setKeyboardVisibility(mLidState == LID_OPEN); } void updateRotation(boolean alwaysSendConfiguration) { @@ -4078,7 +4074,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // even if the keyguard is up, now that all the wakelocks have been released, we // should re-enable the screen saver mScreenSaverMayRun = true; - updateScreenSaverTimeoutLocked(); } } } @@ -4136,7 +4131,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); pw.print(" mSystemReady="); pw.print(mSystemReady); pw.print(" mSystemBooted="); pw.println(mSystemBooted); - pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen); + pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp index ef7fa16..7a4986b 100644 --- a/services/common_time/common_time_server.cpp +++ b/services/common_time/common_time_server.cpp @@ -80,14 +80,14 @@ const int CommonTimeServer::kInitial_WhoIsMasterTimeoutMs = 500; // number of sync requests that can fail before a client assumes its master // is dead -const int CommonTimeServer::kClient_NumSyncRequestRetries = 5; +const int CommonTimeServer::kClient_NumSyncRequestRetries = 10; /*** Master state constants ***/ /*** Ronin state constants ***/ // number of WhoIsMaster attempts sent before declaring ourselves master -const int CommonTimeServer::kRonin_NumWhoIsMasterRetries = 4; +const int CommonTimeServer::kRonin_NumWhoIsMasterRetries = 20; // timeout used when waiting for a response to a WhoIsMaster request const int CommonTimeServer::kRonin_WhoIsMasterTimeoutMs = 500; @@ -96,7 +96,7 @@ const int CommonTimeServer::kRonin_WhoIsMasterTimeoutMs = 500; // how long do we wait for an announcement from a master before // trying another election? -const int CommonTimeServer::kWaitForElection_TimeoutMs = 5000; +const int CommonTimeServer::kWaitForElection_TimeoutMs = 12500; CommonTimeServer::CommonTimeServer() : Thread(false) @@ -279,10 +279,14 @@ bool CommonTimeServer::runStateMachine_l() { // If we were in the master state, then either we were the // master in a no-network situation, or we were the master // of a different network and have moved to a new interface. - // In either case, immediately send out a master - // announcement at low priority. + // In either case, immediately transition to Ronin at low + // priority. If there is no one in the network we just + // joined, we will become master soon enough. If there is, + // we want to be certain to defer master status to the + // existing timeline currently running on the network. + // case CommonClockService::STATE_MASTER: - sendMasterAnnouncement(); + becomeRonin("leaving networkless mode"); break; // If we were in any other state (CLIENT, RONIN, or @@ -1072,6 +1076,12 @@ bool CommonTimeServer::becomeClient(const sockaddr_storage& masterEP, mMasterEP = masterEP; mMasterEPValid = true; + + // If we are on a real network as a client of a real master, then we should + // no longer force low priority. If our master disappears, we should have + // the high priority bit set during the election to replace the master + // because this group was a real group and not a singleton created in + // networkless mode. setForceLowPriority(false); mClient_MasterDeviceID = masterDeviceID; @@ -1113,7 +1123,6 @@ bool CommonTimeServer::becomeMaster(const char* cause) { memset(&mMasterEP, 0, sizeof(mMasterEP)); mMasterEPValid = false; - setForceLowPriority(false); mClient_MasterDevicePriority = effectivePriority(); mClient_MasterDeviceID = mDeviceID; mClockRecovery.reset(false, true); diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp index 665d711..2ba821e 100644 --- a/services/input/EventHub.cpp +++ b/services/input/EventHub.cpp @@ -93,6 +93,34 @@ static String8 sha1(const String8& in) { return out; } +static void setDescriptor(InputDeviceIdentifier& identifier) { + // Compute a device descriptor that uniquely identifies the device. + // The descriptor is assumed to be a stable identifier. Its value should not + // change between reboots, reconnections, firmware updates or new releases of Android. + // Ideally, we also want the descriptor to be short and relatively opaque. + String8 rawDescriptor; + rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product); + if (!identifier.uniqueId.isEmpty()) { + rawDescriptor.append("uniqueId:"); + rawDescriptor.append(identifier.uniqueId); + } if (identifier.vendor == 0 && identifier.product == 0) { + // If we don't know the vendor and product id, then the device is probably + // built-in so we need to rely on other information to uniquely identify + // the input device. Usually we try to avoid relying on the device name or + // location but for built-in input device, they are unlikely to ever change. + if (!identifier.name.isEmpty()) { + rawDescriptor.append("name:"); + rawDescriptor.append(identifier.name); + } else if (!identifier.location.isEmpty()) { + rawDescriptor.append("location:"); + rawDescriptor.append(identifier.location); + } + } + identifier.descriptor = sha1(rawDescriptor); + ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(), + identifier.descriptor.string()); +} + // --- Global Functions --- uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) { @@ -164,7 +192,7 @@ const int EventHub::EPOLL_SIZE_HINT; const int EventHub::EPOLL_MAX_EVENTS; EventHub::EventHub(void) : - mBuiltInKeyboardId(-1), mNextDeviceId(1), + mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mOpeningDevices(0), mClosingDevices(0), mNeedToSendFinishedDeviceScan(false), mNeedToReopenDevices(false), mNeedToScanDevices(true), @@ -256,7 +284,7 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis, AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && test_bit(axis, device->absBitmask)) { + if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) { struct input_absinfo info; if(ioctl(device->fd, EVIOCGABS(axis), &info)) { ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", @@ -307,7 +335,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && test_bit(scanCode, device->keyBitmask)) { + if (device && !device->isVirtual() && test_bit(scanCode, device->keyBitmask)) { uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; memset(keyState, 0, sizeof(keyState)); if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) { @@ -322,7 +350,7 @@ int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && device->keyMap.haveKeyLayout()) { + if (device && !device->isVirtual() && device->keyMap.haveKeyLayout()) { Vector<int32_t> scanCodes; device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes); if (scanCodes.size() != 0) { @@ -347,7 +375,7 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && test_bit(sw, device->swBitmask)) { + if (device && !device->isVirtual() && test_bit(sw, device->swBitmask)) { uint8_t swState[sizeof_bit_array(SW_MAX + 1)]; memset(swState, 0, sizeof(swState)); if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) { @@ -365,7 +393,7 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && test_bit(axis, device->absBitmask)) { + if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) { struct input_absinfo info; if(ioctl(device->fd, EVIOCGABS(axis), &info)) { ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", @@ -408,58 +436,35 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, return false; } -status_t EventHub::mapKey(int32_t deviceId, int scancode, - int32_t* outKeycode, uint32_t* outFlags) const -{ +status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, + int32_t* outKeycode, uint32_t* outFlags) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - + if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapKey(scancode, outKeycode, outFlags); + status_t err = device->keyMap.keyLayoutMap->mapKey( + scanCode, usageCode, outKeycode, outFlags); if (err == NO_ERROR) { return NO_ERROR; } } - - if (mBuiltInKeyboardId != -1) { - device = getDeviceLocked(mBuiltInKeyboardId); - - if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapKey(scancode, outKeycode, outFlags); - if (err == NO_ERROR) { - return NO_ERROR; - } - } - } - + *outKeycode = 0; *outFlags = 0; return NAME_NOT_FOUND; } -status_t EventHub::mapAxis(int32_t deviceId, int scancode, AxisInfo* outAxisInfo) const -{ +status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo); + status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo); if (err == NO_ERROR) { return NO_ERROR; } } - if (mBuiltInKeyboardId != -1) { - device = getDeviceLocked(mBuiltInKeyboardId); - - if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo); - if (err == NO_ERROR) { - return NO_ERROR; - } - } - } - return NAME_NOT_FOUND; } @@ -494,7 +499,7 @@ bool EventHub::hasLed(int32_t deviceId, int32_t led) const { void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && led >= 0 && led <= LED_MAX) { + if (device && !device->isVirtual() && led >= 0 && led <= LED_MAX) { struct input_event ev; ev.time.tv_sec = 0; ev.time.tv_usec = 0; @@ -520,17 +525,17 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId, } } -String8 EventHub::getKeyCharacterMapFile(int32_t deviceId) const { +sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { - return device->keyMap.keyCharacterMapFile; + return device->keyMap.keyCharacterMap; } - return String8(); + return NULL; } EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const { - if (deviceId == 0) { + if (deviceId == BUILT_IN_KEYBOARD_ID) { deviceId = mBuiltInKeyboardId; } ssize_t index = mDevices.indexOfKey(deviceId); @@ -578,7 +583,7 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz device->id, device->path.string()); mClosingDevices = device->next; event->when = now; - event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; + event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id; event->type = DEVICE_REMOVED; event += 1; delete device; @@ -703,16 +708,8 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz #endif event->deviceId = deviceId; event->type = iev.type; - event->scanCode = iev.code; + event->code = iev.code; event->value = iev.value; - event->keyCode = AKEYCODE_UNKNOWN; - event->flags = 0; - if (iev.type == EV_KEY && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapKey(iev.code, - &event->keyCode, &event->flags); - ALOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n", - iev.code, event->keyCode, event->flags, err); - } event += 1; } capacity -= count; @@ -813,6 +810,9 @@ void EventHub::scanDevicesLocked() { if(res < 0) { ALOGE("scan dir failed for %s\n", DEVICE_PATH); } + if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) { + createVirtualKeyboardLocked(); + } } // ---------------------------------------------------------------------------- @@ -908,29 +908,8 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { identifier.uniqueId.setTo(buffer); } - // Compute a device descriptor that uniquely identifies the device. - // The descriptor is assumed to be a stable identifier. Its value should not - // change between reboots, reconnections, firmware updates or new releases of Android. - // Ideally, we also want the descriptor to be short and relatively opaque. - String8 rawDescriptor; - rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product); - if (!identifier.uniqueId.isEmpty()) { - rawDescriptor.append("uniqueId:"); - rawDescriptor.append(identifier.uniqueId); - } if (identifier.vendor == 0 && identifier.product == 0) { - // If we don't know the vendor and product id, then the device is probably - // built-in so we need to rely on other information to uniquely identify - // the input device. Usually we try to avoid relying on the device name or - // location but for built-in input device, they are unlikely to ever change. - if (!identifier.name.isEmpty()) { - rawDescriptor.append("name:"); - rawDescriptor.append(identifier.name); - } else if (!identifier.location.isEmpty()) { - rawDescriptor.append("location:"); - rawDescriptor.append(identifier.location); - } - } - identifier.descriptor = sha1(rawDescriptor); + // Fill in the descriptor. + setDescriptor(identifier); // Make file descriptor non-blocking for use with poll(). if (fcntl(fd, F_SETFL, O_NONBLOCK)) { @@ -952,7 +931,7 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { ALOGV(" name: \"%s\"\n", identifier.name.string()); ALOGV(" location: \"%s\"\n", identifier.location.string()); ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string()); - ALOGV(" descriptor: \"%s\" (%s)\n", identifier.descriptor.string(), rawDescriptor.string()); + ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.string()); ALOGV(" driver: v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff); @@ -1048,7 +1027,7 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) { // Register the keyboard as a built-in keyboard if it is eligible. if (!keyMapStatus - && mBuiltInKeyboardId == -1 + && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD && isEligibleBuiltInKeyboard(device->identifier, device->configuration, &device->keyMap)) { mBuiltInKeyboardId = device->id; @@ -1103,24 +1082,59 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { // Enable wake-lock behavior on kernels that support it. // TODO: Only need this for devices that can really wake the system. - bool usingSuspendBlock = ioctl(fd, EVIOCSSUSPENDBLOCK, 1) == 0; + bool usingSuspendBlockIoctl = !ioctl(fd, EVIOCSSUSPENDBLOCK, 1); + + // Tell the kernel that we want to use the monotonic clock for reporting timestamps + // associated with input events. This is important because the input system + // uses the timestamps extensively and assumes they were recorded using the monotonic + // clock. + // + // In older kernel, before Linux 3.4, there was no way to tell the kernel which + // clock to use to input event timestamps. The standard kernel behavior was to + // record a real time timestamp, which isn't what we want. Android kernels therefore + // contained a patch to the evdev_event() function in drivers/input/evdev.c to + // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic + // clock to be used instead of the real time clock. + // + // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock. + // Therefore, we no longer require the Android-specific kernel patch described above + // as long as we make sure to set select the monotonic clock. We do that here. + bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, CLOCK_MONOTONIC); ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, " "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, " - "usingSuspendBlock=%s", + "usingSuspendBlockIoctl=%s, usingClockIoctl=%s", deviceId, fd, devicePath, device->identifier.name.string(), device->classes, device->configurationFile.string(), device->keyMap.keyLayoutFile.string(), device->keyMap.keyCharacterMapFile.string(), toString(mBuiltInKeyboardId == deviceId), - toString(usingSuspendBlock)); + toString(usingSuspendBlockIoctl), toString(usingClockIoctl)); - mDevices.add(deviceId, device); + addDeviceLocked(device); + return 0; +} +void EventHub::createVirtualKeyboardLocked() { + InputDeviceIdentifier identifier; + identifier.name = "Virtual"; + identifier.uniqueId = "<virtual>"; + setDescriptor(identifier); + + Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier); + device->classes = INPUT_DEVICE_CLASS_KEYBOARD + | INPUT_DEVICE_CLASS_ALPHAKEY + | INPUT_DEVICE_CLASS_DPAD + | INPUT_DEVICE_CLASS_VIRTUAL; + loadKeyMapLocked(device); + addDeviceLocked(device); +} + +void EventHub::addDeviceLocked(Device* device) { + mDevices.add(device->id, device); device->next = mOpeningDevices; mOpeningDevices = device; - return 0; } void EventHub::loadConfigurationLocked(Device* device) { @@ -1207,11 +1221,13 @@ void EventHub::closeDeviceLocked(Device* device) { if (device->id == mBuiltInKeyboardId) { ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this", device->path.string(), mBuiltInKeyboardId); - mBuiltInKeyboardId = -1; + mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD; } - if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) { - ALOGW("Could not remove device fd from epoll instance. errno=%d", errno); + if (!device->isVirtual()) { + if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) { + ALOGW("Could not remove device fd from epoll instance. errno=%d", errno); + } } mDevices.removeItem(device->id); diff --git a/services/input/EventHub.h b/services/input/EventHub.h index bd21a3d..88159e7 100644 --- a/services/input/EventHub.h +++ b/services/input/EventHub.h @@ -19,6 +19,7 @@ #define _RUNTIME_EVENT_HUB_H #include <androidfw/Input.h> +#include <androidfw/InputDevice.h> #include <androidfw/Keyboard.h> #include <androidfw/KeyLayoutMap.h> #include <androidfw/KeyCharacterMap.h> @@ -38,11 +39,18 @@ /* Convenience constants. */ -#define BTN_FIRST 0x100 // first button scancode -#define BTN_LAST 0x15f // last button scancode +#define BTN_FIRST 0x100 // first button code +#define BTN_LAST 0x15f // last button code namespace android { +enum { + // Device id of a special "virtual" keyboard that is always present. + VIRTUAL_KEYBOARD_ID = -1, + // Device id of the "built-in" keyboard if there is one. + BUILT_IN_KEYBOARD_ID = 0, +}; + /* * A raw event as retrieved from the EventHub. */ @@ -50,10 +58,8 @@ struct RawEvent { nsecs_t when; int32_t deviceId; int32_t type; - int32_t scanCode; - int32_t keyCode; + int32_t code; int32_t value; - uint32_t flags; }; /* Describes an absolute axis. */ @@ -107,6 +113,9 @@ enum { /* The input device is a joystick (implies gamepad, has joystick absolute axes). */ INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100, + /* The input device is virtual (not a real device, not part of UI configuration). */ + INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000, + /* The input device is external (not built-in). */ INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000, }; @@ -162,10 +171,10 @@ public: virtual bool hasInputProperty(int32_t deviceId, int property) const = 0; - virtual status_t mapKey(int32_t deviceId, int scancode, + virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t* outKeycode, uint32_t* outFlags) const = 0; - virtual status_t mapAxis(int32_t deviceId, int scancode, + virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const = 0; // Sets devices that are excluded from opening. @@ -208,7 +217,7 @@ public: virtual void getVirtualKeyDefinitions(int32_t deviceId, Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0; - virtual String8 getKeyCharacterMapFile(int32_t deviceId) const = 0; + virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const = 0; /* Requests the EventHub to reopen all input devices on the next call to getEvents(). */ virtual void requestReopenDevices() = 0; @@ -241,10 +250,10 @@ public: virtual bool hasInputProperty(int32_t deviceId, int property) const; - virtual status_t mapKey(int32_t deviceId, int scancode, + virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t* outKeycode, uint32_t* outFlags) const; - virtual status_t mapAxis(int32_t deviceId, int scancode, + virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const; virtual void setExcludedDevices(const Vector<String8>& devices); @@ -266,7 +275,7 @@ public: virtual void getVirtualKeyDefinitions(int32_t deviceId, Vector<VirtualKeyDefinition>& outVirtualKeys) const; - virtual String8 getKeyCharacterMapFile(int32_t deviceId) const; + virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const; virtual void requestReopenDevices(); @@ -282,7 +291,7 @@ private: struct Device { Device* next; - int fd; + int fd; // may be -1 if device is virtual const int32_t id; const String8 path; const InputDeviceIdentifier identifier; @@ -305,11 +314,15 @@ private: ~Device(); void close(); + + inline bool isVirtual() const { return fd < 0; } }; status_t openDeviceLocked(const char *devicePath); - status_t closeDeviceByPathLocked(const char *devicePath); + void createVirtualKeyboardLocked(); + void addDeviceLocked(Device* device); + status_t closeDeviceByPathLocked(const char *devicePath); void closeDeviceLocked(Device* device); void closeAllDevicesLocked(); @@ -331,8 +344,13 @@ private: // Protect all internal state. mutable Mutex mLock; - // The actual id of the built-in keyboard, or -1 if none. + // The actual id of the built-in keyboard, or NO_BUILT_IN_KEYBOARD if none. // EventHub remaps the built-in keyboard to id 0 externally as required by the API. + enum { + // Must not conflict with any other assigned device ids, including + // the virtual keyboard id (-1). + NO_BUILT_IN_KEYBOARD = -2, + }; int32_t mBuiltInKeyboardId; int32_t mNextDeviceId; diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index ddd870d..ea614ad 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -523,19 +523,21 @@ void InputReader::updateInputConfigurationLocked() { InputDeviceInfo deviceInfo; for (size_t i = 0; i < mDevices.size(); i++) { InputDevice* device = mDevices.valueAt(i); - device->getDeviceInfo(& deviceInfo); - uint32_t sources = deviceInfo.getSources(); + if (!(device->getClasses() & INPUT_DEVICE_CLASS_VIRTUAL)) { + device->getDeviceInfo(& deviceInfo); + uint32_t sources = deviceInfo.getSources(); - if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) { - touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER; - } - if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) { - navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL; - } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) { - navigationConfig = InputConfiguration::NAVIGATION_DPAD; - } - if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) { - keyboardConfig = InputConfiguration::KEYBOARD_QWERTY; + if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) { + touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER; + } + if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) { + navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL; + } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) { + navigationConfig = InputConfiguration::NAVIGATION_DPAD; + } + if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) { + keyboardConfig = InputConfiguration::KEYBOARD_QWERTY; + } } } @@ -944,14 +946,12 @@ void InputDevice::process(const RawEvent* rawEvents, size_t count) { size_t numMappers = mMappers.size(); for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { #if DEBUG_RAW_EVENTS - ALOGD("Input event: device=%d type=0x%04x scancode=0x%04x " - "keycode=0x%04x value=0x%08x flags=0x%08x", - rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode, - rawEvent->value, rawEvent->flags); + ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x", + rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value); #endif if (mDropUntilNextSync) { - if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) { + if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { mDropUntilNextSync = false; #if DEBUG_RAW_EVENTS ALOGD("Recovered from input event buffer overrun."); @@ -961,7 +961,7 @@ void InputDevice::process(const RawEvent* rawEvents, size_t count) { ALOGD("Dropped input event while waiting for next input sync."); #endif } - } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) { + } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) { ALOGI("Detected input event buffer overrun for device %s.", getName().string()); mDropUntilNextSync = true; reset(rawEvent->when); @@ -1090,7 +1090,7 @@ void CursorButtonAccumulator::clearButtons() { void CursorButtonAccumulator::process(const RawEvent* rawEvent) { if (rawEvent->type == EV_KEY) { - switch (rawEvent->scanCode) { + switch (rawEvent->code) { case BTN_LEFT: mBtnLeft = rawEvent->value; break; @@ -1157,7 +1157,7 @@ void CursorMotionAccumulator::clearRelativeAxes() { void CursorMotionAccumulator::process(const RawEvent* rawEvent) { if (rawEvent->type == EV_REL) { - switch (rawEvent->scanCode) { + switch (rawEvent->code) { case REL_X: mRelX = rawEvent->value; break; @@ -1196,7 +1196,7 @@ void CursorScrollAccumulator::clearRelativeAxes() { void CursorScrollAccumulator::process(const RawEvent* rawEvent) { if (rawEvent->type == EV_REL) { - switch (rawEvent->scanCode) { + switch (rawEvent->code) { case REL_WHEEL: mRelWheel = rawEvent->value; break; @@ -1259,7 +1259,7 @@ void TouchButtonAccumulator::clearButtons() { void TouchButtonAccumulator::process(const RawEvent* rawEvent) { if (rawEvent->type == EV_KEY) { - switch (rawEvent->scanCode) { + switch (rawEvent->code) { case BTN_TOUCH: mBtnTouch = rawEvent->value; break; @@ -1465,7 +1465,7 @@ void SingleTouchMotionAccumulator::clearAbsoluteAxes() { void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) { if (rawEvent->type == EV_ABS) { - switch (rawEvent->scanCode) { + switch (rawEvent->code) { case ABS_X: mAbsX = rawEvent->value; break; @@ -1549,7 +1549,7 @@ void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { if (rawEvent->type == EV_ABS) { bool newSlot = false; if (mUsingSlotsProtocol) { - if (rawEvent->scanCode == ABS_MT_SLOT) { + if (rawEvent->code == ABS_MT_SLOT) { mCurrentSlot = rawEvent->value; newSlot = true; } @@ -1568,7 +1568,7 @@ void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { } else { Slot* slot = &mSlots[mCurrentSlot]; - switch (rawEvent->scanCode) { + switch (rawEvent->code) { case ABS_MT_POSITION_X: slot->mInUse = true; slot->mAbsMTPositionX = rawEvent->value; @@ -1624,7 +1624,7 @@ void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { break; } } - } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_MT_REPORT) { + } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) { // MultiTouch Sync: The driver has returned all data for *one* of the pointers. mCurrentSlot += 1; } @@ -1755,7 +1755,7 @@ uint32_t SwitchInputMapper::getSources() { void SwitchInputMapper::process(const RawEvent* rawEvent) { switch (rawEvent->type) { case EV_SW: - processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value); + processSwitch(rawEvent->when, rawEvent->code, rawEvent->value); break; } } @@ -1789,7 +1789,7 @@ void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) { InputMapper::populateDeviceInfo(info); info->setKeyboardType(mKeyboardType); - info->setKeyCharacterMapFile(getEventHub()->getKeyCharacterMapFile(getDeviceId())); + info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId())); } void KeyboardInputMapper::dump(String8& dump) { @@ -1847,6 +1847,7 @@ void KeyboardInputMapper::reset(nsecs_t when) { mMetaState = AMETA_NONE; mDownTime = 0; mKeyDowns.clear(); + mCurrentHidUsage = 0; resetLedState(); @@ -1856,13 +1857,32 @@ void KeyboardInputMapper::reset(nsecs_t when) { void KeyboardInputMapper::process(const RawEvent* rawEvent) { switch (rawEvent->type) { case EV_KEY: { - int32_t scanCode = rawEvent->scanCode; + int32_t scanCode = rawEvent->code; + int32_t usageCode = mCurrentHidUsage; + mCurrentHidUsage = 0; + if (isKeyboardOrGamepadKey(scanCode)) { - processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode, - rawEvent->flags); + int32_t keyCode; + uint32_t flags; + if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) { + keyCode = AKEYCODE_UNKNOWN; + flags = 0; + } + processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags); + } + break; + } + case EV_MSC: { + if (rawEvent->code == MSC_SCAN) { + mCurrentHidUsage = rawEvent->value; } break; } + case EV_SYN: { + if (rawEvent->code == SYN_REPORT) { + mCurrentHidUsage = 0; + } + } } } @@ -2181,7 +2201,7 @@ void CursorInputMapper::process(const RawEvent* rawEvent) { mCursorMotionAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); - if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) { + if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { sync(rawEvent->when); } } @@ -3014,8 +3034,7 @@ void TouchInputMapper::configureVirtualKeys() { virtualKey.scanCode = virtualKeyDefinition.scanCode; int32_t keyCode; uint32_t flags; - if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, - & keyCode, & flags)) { + if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) { ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode); mVirtualKeys.pop(); // drop the key @@ -3309,7 +3328,7 @@ void TouchInputMapper::process(const RawEvent* rawEvent) { mCursorScrollAccumulator.process(rawEvent); mTouchButtonAccumulator.process(rawEvent); - if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) { + if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { sync(rawEvent->when); } } @@ -5918,7 +5937,7 @@ void JoystickInputMapper::reset(nsecs_t when) { void JoystickInputMapper::process(const RawEvent* rawEvent) { switch (rawEvent->type) { case EV_ABS: { - ssize_t index = mAxes.indexOfKey(rawEvent->scanCode); + ssize_t index = mAxes.indexOfKey(rawEvent->code); if (index >= 0) { Axis& axis = mAxes.editValueAt(index); float newValue, highNewValue; @@ -5954,7 +5973,7 @@ void JoystickInputMapper::process(const RawEvent* rawEvent) { } case EV_SYN: - switch (rawEvent->scanCode) { + switch (rawEvent->code) { case SYN_REPORT: sync(rawEvent->when, false /*force*/); break; diff --git a/services/input/InputReader.h b/services/input/InputReader.h index 8520a75..8ab5905 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -904,6 +904,8 @@ private: int32_t mMetaState; nsecs_t mDownTime; // time of most recent key down + int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none + struct LedState { bool avail; // led is available bool on; // we think the led is currently on diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 2cccf9f..eac9a1c 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -283,7 +283,8 @@ class FakeEventHub : public EventHubInterface { KeyedVector<int32_t, int32_t> scanCodeStates; KeyedVector<int32_t, int32_t> switchStates; KeyedVector<int32_t, int32_t> absoluteAxisValue; - KeyedVector<int32_t, KeyInfo> keys; + KeyedVector<int32_t, KeyInfo> keysByScanCode; + KeyedVector<int32_t, KeyInfo> keysByUsageCode; KeyedVector<int32_t, bool> leds; Vector<VirtualKeyDefinition> virtualKeys; @@ -311,18 +312,18 @@ public: device->identifier.name = name; mDevices.add(deviceId, device); - enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0, 0, 0); + enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0); } void removeDevice(int32_t deviceId) { delete mDevices.valueFor(deviceId); mDevices.removeItem(deviceId); - enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0, 0, 0); + enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0); } void finishDeviceScan() { - enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0, 0, 0); + enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0); } void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) { @@ -374,12 +375,18 @@ public: device->absoluteAxisValue.replaceValueFor(axis, value); } - void addKey(int32_t deviceId, int32_t scanCode, int32_t keyCode, uint32_t flags) { + void addKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, + int32_t keyCode, uint32_t flags) { Device* device = getDevice(deviceId); KeyInfo info; info.keyCode = keyCode; info.flags = flags; - device->keys.add(scanCode, info); + if (scanCode) { + device->keysByScanCode.add(scanCode, info); + } + if (usageCode) { + device->keysByUsageCode.add(usageCode, info); + } } void addLed(int32_t deviceId, int32_t led, bool initialState) { @@ -402,19 +409,17 @@ public: } void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type, - int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) { + int32_t code, int32_t value) { RawEvent event; event.when = when; event.deviceId = deviceId; event.type = type; - event.scanCode = scanCode; - event.keyCode = keyCode; + event.code = code; event.value = value; - event.flags = flags; mEvents.push_back(event); if (type == EV_ABS) { - setAbsoluteAxisValue(deviceId, scanCode, value); + setAbsoluteAxisValue(deviceId, code, value); } } @@ -471,17 +476,17 @@ private: return false; } - virtual status_t mapKey(int32_t deviceId, int scancode, + virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t* outKeycode, uint32_t* outFlags) const { Device* device = getDevice(deviceId); if (device) { - ssize_t index = device->keys.indexOfKey(scancode); - if (index >= 0) { + const KeyInfo* key = getKey(device, scanCode, usageCode); + if (key) { if (outKeycode) { - *outKeycode = device->keys.valueAt(index).keyCode; + *outKeycode = key->keyCode; } if (outFlags) { - *outFlags = device->keys.valueAt(index).flags; + *outFlags = key->flags; } return OK; } @@ -489,7 +494,23 @@ private: return NAME_NOT_FOUND; } - virtual status_t mapAxis(int32_t deviceId, int scancode, + const KeyInfo* getKey(Device* device, int32_t scanCode, int32_t usageCode) const { + if (usageCode) { + ssize_t index = device->keysByUsageCode.indexOfKey(usageCode); + if (index >= 0) { + return &device->keysByUsageCode.valueAt(index); + } + } + if (scanCode) { + ssize_t index = device->keysByScanCode.indexOfKey(scanCode); + if (index >= 0) { + return &device->keysByScanCode.valueAt(index); + } + } + return NULL; + } + + virtual status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const { return NAME_NOT_FOUND; } @@ -561,8 +582,14 @@ private: Device* device = getDevice(deviceId); if (device) { for (size_t i = 0; i < numCodes; i++) { - for (size_t j = 0; j < device->keys.size(); j++) { - if (keyCodes[i] == device->keys.valueAt(j).keyCode) { + for (size_t j = 0; j < device->keysByScanCode.size(); j++) { + if (keyCodes[i] == device->keysByScanCode.valueAt(j).keyCode) { + outFlags[i] = 1; + result = true; + } + } + for (size_t j = 0; j < device->keysByUsageCode.size(); j++) { + if (keyCodes[i] == device->keysByUsageCode.valueAt(j).keyCode) { outFlags[i] = 1; result = true; } @@ -575,7 +602,7 @@ private: virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const { Device* device = getDevice(deviceId); if (device) { - ssize_t index = device->keys.indexOfKey(scanCode); + ssize_t index = device->keysByScanCode.indexOfKey(scanCode); return index >= 0; } return false; @@ -610,8 +637,8 @@ private: } } - virtual String8 getKeyCharacterMapFile(int32_t deviceId) const { - return String8(); + virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const { + return NULL; } virtual bool isExternal(int32_t deviceId) const { @@ -1196,7 +1223,7 @@ TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"), INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL)); - mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, AKEYCODE_A, 1, POLICY_FLAG_WAKE); + mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, 1); mReader->loopOnce(); ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty()); @@ -1205,10 +1232,8 @@ TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { ASSERT_EQ(0, event.when); ASSERT_EQ(1, event.deviceId); ASSERT_EQ(EV_KEY, event.type); - ASSERT_EQ(KEY_A, event.scanCode); - ASSERT_EQ(AKEYCODE_A, event.keyCode); + ASSERT_EQ(KEY_A, event.code); ASSERT_EQ(1, event.value); - ASSERT_EQ(POLICY_FLAG_WAKE, event.flags); } @@ -1449,15 +1474,13 @@ protected: } static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type, - int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) { + int32_t code, int32_t value) { RawEvent event; event.when = when; event.deviceId = deviceId; event.type = type; - event.scanCode = scanCode; - event.keyCode = keyCode; + event.code = code; event.value = value; - event.flags = flags; mapper->process(&event); } @@ -1530,7 +1553,7 @@ TEST_F(SwitchInputMapperTest, Process) { SwitchInputMapper* mapper = new SwitchInputMapper(mDevice); addMapperAndConfigure(mapper); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 0, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 1); NotifySwitchArgs args; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySwitchWasCalled(&args)); @@ -1553,13 +1576,13 @@ void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper, int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) { NotifyKeyArgs args; - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); ASSERT_EQ(originalScanCode, args.scanCode); ASSERT_EQ(rotatedKeyCode, args.keyCode); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); ASSERT_EQ(originalScanCode, args.scanCode); @@ -1576,13 +1599,18 @@ TEST_F(KeyboardInputMapperTest, GetSources) { } TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { + const int32_t USAGE_A = 0x070004; + const int32_t USAGE_UNKNOWN = 0x07ffff; + mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE); + mFakeEventHub->addKey(DEVICE_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE); + KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); addMapperAndConfigure(mapper); - // Key down. + // Key down by scan code. process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE); + EV_KEY, KEY_HOME, 1); NotifyKeyArgs args; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); @@ -1596,9 +1624,9 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); ASSERT_EQ(ARBITRARY_TIME, args.downTime); - // Key up. + // Key up by scan code. process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, - EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE); + EV_KEY, KEY_HOME, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(DEVICE_ID, args.deviceId); ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); @@ -1610,9 +1638,80 @@ TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) { ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags); ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); ASSERT_EQ(ARBITRARY_TIME, args.downTime); + + // Key down by usage code. + process(mapper, ARBITRARY_TIME, DEVICE_ID, + EV_MSC, MSC_SCAN, USAGE_A); + process(mapper, ARBITRARY_TIME, DEVICE_ID, + EV_KEY, 0, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(DEVICE_ID, args.deviceId); + ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); + ASSERT_EQ(ARBITRARY_TIME, args.eventTime); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); + ASSERT_EQ(AKEYCODE_A, args.keyCode); + ASSERT_EQ(0, args.scanCode); + ASSERT_EQ(AMETA_NONE, args.metaState); + ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); + ASSERT_EQ(ARBITRARY_TIME, args.downTime); + + // Key up by usage code. + process(mapper, ARBITRARY_TIME, DEVICE_ID, + EV_MSC, MSC_SCAN, USAGE_A); + process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, + EV_KEY, 0, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(DEVICE_ID, args.deviceId); + ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); + ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); + ASSERT_EQ(AKEYCODE_A, args.keyCode); + ASSERT_EQ(0, args.scanCode); + ASSERT_EQ(AMETA_NONE, args.metaState); + ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags); + ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags); + ASSERT_EQ(ARBITRARY_TIME, args.downTime); + + // Key down with unknown scan code or usage code. + process(mapper, ARBITRARY_TIME, DEVICE_ID, + EV_MSC, MSC_SCAN, USAGE_UNKNOWN); + process(mapper, ARBITRARY_TIME, DEVICE_ID, + EV_KEY, KEY_UNKNOWN, 1); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(DEVICE_ID, args.deviceId); + ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); + ASSERT_EQ(ARBITRARY_TIME, args.eventTime); + ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); + ASSERT_EQ(0, args.keyCode); + ASSERT_EQ(KEY_UNKNOWN, args.scanCode); + ASSERT_EQ(AMETA_NONE, args.metaState); + ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags); + ASSERT_EQ(0U, args.policyFlags); + ASSERT_EQ(ARBITRARY_TIME, args.downTime); + + // Key up with unknown scan code or usage code. + process(mapper, ARBITRARY_TIME, DEVICE_ID, + EV_MSC, MSC_SCAN, USAGE_UNKNOWN); + process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, + EV_KEY, KEY_UNKNOWN, 0); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); + ASSERT_EQ(DEVICE_ID, args.deviceId); + ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source); + ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime); + ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); + ASSERT_EQ(0, args.keyCode); + ASSERT_EQ(KEY_UNKNOWN, args.scanCode); + ASSERT_EQ(AMETA_NONE, args.metaState); + ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags); + ASSERT_EQ(0U, args.policyFlags); + ASSERT_EQ(ARBITRARY_TIME, args.downTime); } TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { + mFakeEventHub->addKey(DEVICE_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_A, 0, AKEYCODE_A, 0); + KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); addMapperAndConfigure(mapper); @@ -1622,7 +1721,7 @@ TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { // Metakey down. process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0); + EV_KEY, KEY_LEFTSHIFT, 1); NotifyKeyArgs args; ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); @@ -1631,21 +1730,21 @@ TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { // Key down. process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, - EV_KEY, KEY_A, AKEYCODE_A, 1, 0); + EV_KEY, KEY_A, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState()); // Key up. process(mapper, ARBITRARY_TIME + 2, DEVICE_ID, - EV_KEY, KEY_A, AKEYCODE_A, 0, 0); + EV_KEY, KEY_A, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState); ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState()); // Metakey up. process(mapper, ARBITRARY_TIME + 3, DEVICE_ID, - EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 0, 0); + EV_KEY, KEY_LEFTSHIFT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AMETA_NONE, args.metaState); ASSERT_EQ(AMETA_NONE, mapper->getMetaState()); @@ -1653,6 +1752,11 @@ TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) { } TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) { + mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0); + KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); addMapperAndConfigure(mapper); @@ -1671,6 +1775,11 @@ TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateD } TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) { + mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0); + KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); addConfigurationProperty("keyboard.orientationAware", "1"); @@ -1731,7 +1840,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) { setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_270); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 1, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action); ASSERT_EQ(KEY_UP, args.scanCode); @@ -1740,7 +1849,7 @@ TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) { setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_180); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action); ASSERT_EQ(KEY_UP, args.scanCode); @@ -1776,7 +1885,7 @@ TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) { AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); addMapperAndConfigure(mapper); - mFakeEventHub->addKey(DEVICE_ID, KEY_A, AKEYCODE_A, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_A, 0, AKEYCODE_A, 0); const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B }; uint8_t flags[2] = { 0, 0 }; @@ -1789,6 +1898,9 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) mFakeEventHub->addLed(DEVICE_ID, LED_CAPSL, true /*initially on*/); mFakeEventHub->addLed(DEVICE_ID, LED_NUML, false /*initially off*/); mFakeEventHub->addLed(DEVICE_ID, LED_SCROLLL, false /*initially off*/); + mFakeEventHub->addKey(DEVICE_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0); + mFakeEventHub->addKey(DEVICE_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0); KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC); @@ -1801,9 +1913,9 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) // Toggle caps lock on. process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0); + EV_KEY, KEY_CAPSLOCK, 1); process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0); + EV_KEY, KEY_CAPSLOCK, 0); ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL)); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML)); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL)); @@ -1811,9 +1923,9 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) // Toggle num lock on. process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0); + EV_KEY, KEY_NUMLOCK, 1); process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0); + EV_KEY, KEY_NUMLOCK, 0); ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL)); ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML)); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL)); @@ -1821,9 +1933,9 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) // Toggle caps lock off. process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0); + EV_KEY, KEY_CAPSLOCK, 1); process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0); + EV_KEY, KEY_CAPSLOCK, 0); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL)); ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML)); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL)); @@ -1831,9 +1943,9 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) // Toggle scroll lock on. process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0); + EV_KEY, KEY_SCROLLLOCK, 1); process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0); + EV_KEY, KEY_SCROLLLOCK, 0); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL)); ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML)); ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL)); @@ -1841,9 +1953,9 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) // Toggle num lock off. process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0); + EV_KEY, KEY_NUMLOCK, 1); process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0); + EV_KEY, KEY_NUMLOCK, 0); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL)); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML)); ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL)); @@ -1851,9 +1963,9 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) // Toggle scroll lock off. process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0); + EV_KEY, KEY_SCROLLLOCK, 1); process(mapper, ARBITRARY_TIME, DEVICE_ID, - EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0); + EV_KEY, KEY_SCROLLLOCK, 0); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL)); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML)); ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL)); @@ -1886,9 +1998,9 @@ void CursorInputMapperTest::testMotionRotation(CursorInputMapper* mapper, int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) { NotifyMotionArgs args; - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, originalX, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, originalY, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, originalX); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, originalY); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -1974,8 +2086,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat // Button press. // Mostly testing non x/y behavior here so we don't need to check again elsewhere. - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); @@ -1996,8 +2108,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaStat ASSERT_EQ(ARBITRARY_TIME, args.downTime); // Button release. Should have same down time. - process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0); - process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0); + process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime); ASSERT_EQ(DEVICE_ID, args.deviceId); @@ -2026,16 +2138,16 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) { NotifyMotionArgs args; // Motion in X but not Y. - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Motion in Y but not X. - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, -2); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2050,16 +2162,16 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) { NotifyMotionArgs args; // Button press. - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Button release. - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2074,10 +2186,10 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { NotifyMotionArgs args; // Combined X, Y and Button. - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, -2); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2085,9 +2197,9 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Move X, Y a bit while pressed. - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 2, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 2); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2095,8 +2207,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // Release Button. - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2185,8 +2297,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { NotifyKeyArgs keyArgs; // press BTN_LEFT, release BTN_LEFT - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState); @@ -2194,8 +2306,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(0, motionArgs.buttonState); ASSERT_EQ(0, mFakePointerController->getButtonState()); @@ -2211,9 +2323,9 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action); ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY, @@ -2223,8 +2335,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState); ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, mFakePointerController->getButtonState()); @@ -2232,8 +2344,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(0, motionArgs.buttonState); ASSERT_EQ(0, mFakePointerController->getButtonState()); @@ -2248,8 +2360,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); // press BTN_BACK, release BTN_BACK - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); @@ -2260,8 +2372,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(0, motionArgs.buttonState); ASSERT_EQ(0, mFakePointerController->getButtonState()); @@ -2273,8 +2385,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); // press BTN_SIDE, release BTN_SIDE - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); @@ -2285,8 +2397,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(0, motionArgs.buttonState); ASSERT_EQ(0, mFakePointerController->getButtonState()); @@ -2298,8 +2410,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode); // press BTN_FORWARD, release BTN_FORWARD - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); @@ -2310,8 +2422,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(0, motionArgs.buttonState); ASSERT_EQ(0, mFakePointerController->getButtonState()); @@ -2323,8 +2435,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); // press BTN_EXTRA, release BTN_EXTRA - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs)); ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action); ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode); @@ -2335,8 +2447,8 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) { ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 0, 0, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs)); ASSERT_EQ(0, motionArgs.buttonState); ASSERT_EQ(0, mFakePointerController->getButtonState()); @@ -2359,9 +2471,9 @@ TEST_F(CursorInputMapperTest, Process_WhenModeIsPointer_ShouldMoveThePointerArou NotifyMotionArgs args; - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 10, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 20, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 10); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 20); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action); ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], @@ -2462,8 +2574,8 @@ void TouchInputMapperTest::prepareDisplay(int32_t orientation) { void TouchInputMapperTest::prepareVirtualKeys() { mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]); mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]); - mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE); - mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, AKEYCODE_MENU, POLICY_FLAG_WAKE); + mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE); + mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE); } int32_t TouchInputMapperTest::toRawX(float displayX) { @@ -2502,7 +2614,7 @@ protected: }; void SingleTouchInputMapperTest::prepareButtons() { - mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, AKEYCODE_UNKNOWN, 0); + mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0); } void SingleTouchInputMapperTest::prepareAxes(int axes) { @@ -2533,48 +2645,48 @@ void SingleTouchInputMapperTest::prepareAxes(int axes) { } void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 1, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 1); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, x); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, y); } void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, x); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, y); } void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper* mapper) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0); } void SingleTouchInputMapperTest::processPressure( SingleTouchInputMapper* mapper, int32_t pressure) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, 0, pressure, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, pressure); } void SingleTouchInputMapperTest::processToolMajor( SingleTouchInputMapper* mapper, int32_t toolMajor) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, 0, toolMajor, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, toolMajor); } void SingleTouchInputMapperTest::processDistance( SingleTouchInputMapper* mapper, int32_t distance) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_DISTANCE, 0, distance, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_DISTANCE, distance); } void SingleTouchInputMapperTest::processTilt( SingleTouchInputMapper* mapper, int32_t tiltX, int32_t tiltY) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_X, 0, tiltX, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_Y, 0, tiltY, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_X, tiltX); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_Y, tiltY); } void SingleTouchInputMapperTest::processKey( SingleTouchInputMapper* mapper, int32_t code, int32_t value) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, 0, value, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, value); } void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); } @@ -3464,7 +3576,7 @@ TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueI prepareDisplay(DISPLAY_ORIENTATION_0); prepareButtons(); prepareAxes(POSITION); - mFakeEventHub->addKey(DEVICE_ID, BTN_TOOL_FINGER, AKEYCODE_UNKNOWN, 0); + mFakeEventHub->addKey(DEVICE_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0); addMapperAndConfigure(mapper); NotifyMotionArgs motionArgs; @@ -3678,71 +3790,71 @@ void MultiTouchInputMapperTest::prepareAxes(int axes) { void MultiTouchInputMapperTest::processPosition( MultiTouchInputMapper* mapper, int32_t x, int32_t y) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, 0, x, 0); - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, 0, y, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, x); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, y); } void MultiTouchInputMapperTest::processTouchMajor( MultiTouchInputMapper* mapper, int32_t touchMajor) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, 0, touchMajor, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor); } void MultiTouchInputMapperTest::processTouchMinor( MultiTouchInputMapper* mapper, int32_t touchMinor) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, 0, touchMinor, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor); } void MultiTouchInputMapperTest::processToolMajor( MultiTouchInputMapper* mapper, int32_t toolMajor) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, 0, toolMajor, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor); } void MultiTouchInputMapperTest::processToolMinor( MultiTouchInputMapper* mapper, int32_t toolMinor) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, 0, toolMinor, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor); } void MultiTouchInputMapperTest::processOrientation( MultiTouchInputMapper* mapper, int32_t orientation) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, 0, orientation, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, orientation); } void MultiTouchInputMapperTest::processPressure( MultiTouchInputMapper* mapper, int32_t pressure) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, 0, pressure, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, pressure); } void MultiTouchInputMapperTest::processDistance( MultiTouchInputMapper* mapper, int32_t distance) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_DISTANCE, 0, distance, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_DISTANCE, distance); } void MultiTouchInputMapperTest::processId( MultiTouchInputMapper* mapper, int32_t id) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, 0, id, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, id); } void MultiTouchInputMapperTest::processSlot( MultiTouchInputMapper* mapper, int32_t slot) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_SLOT, 0, slot, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_SLOT, slot); } void MultiTouchInputMapperTest::processToolType( MultiTouchInputMapper* mapper, int32_t toolType) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOOL_TYPE, 0, toolType, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOOL_TYPE, toolType); } void MultiTouchInputMapperTest::processKey( MultiTouchInputMapper* mapper, int32_t code, int32_t value) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, 0, value, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, value); } void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0); } void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper* mapper) { - process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0); + process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0); } @@ -4891,7 +5003,7 @@ TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIs addConfigurationProperty("touch.deviceType", "touchScreen"); prepareDisplay(DISPLAY_ORIENTATION_0); prepareAxes(POSITION | ID | SLOT); - mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, AKEYCODE_UNKNOWN, 0); + mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0); addMapperAndConfigure(mapper); NotifyMotionArgs motionArgs; diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java index 16eeb7b..b943c09 100644 --- a/services/java/com/android/server/DeviceStorageMonitorService.java +++ b/services/java/com/android/server/DeviceStorageMonitorService.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.os.Binder; +import android.os.Environment; import android.os.Handler; import android.os.Message; import android.os.Process; @@ -336,7 +337,9 @@ public class DeviceStorageMonitorService extends Binder { //log the event to event log with the amount of free storage(in bytes) left on the device EventLog.writeEvent(EventLogTags.LOW_STORAGE, mFreeMem); // Pack up the values and broadcast them to everyone - Intent lowMemIntent = new Intent(Intent.ACTION_MANAGE_PACKAGE_STORAGE); + Intent lowMemIntent = new Intent(Environment.isExternalStorageEmulated() + ? Settings.ACTION_INTERNAL_STORAGE_SETTINGS + : Intent.ACTION_MANAGE_PACKAGE_STORAGE); lowMemIntent.putExtra("memory", mFreeMem); lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); NotificationManager mNotificationMgr = diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 96ee2f0..ca7241c 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -27,6 +27,7 @@ import com.android.internal.view.IInputMethodManager; import com.android.internal.view.IInputMethodSession; import com.android.internal.view.InputBindResult; import com.android.server.EventLogTags; +import com.android.server.wm.WindowManagerService; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -91,7 +92,10 @@ import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.widget.ArrayAdapter; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.RadioButton; +import android.widget.Switch; import android.widget.TextView; import java.io.File; @@ -134,6 +138,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final int MSG_UNBIND_METHOD = 3000; static final int MSG_BIND_METHOD = 3010; + static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000; + static final long TIME_TO_RECONNECT = 10*1000; static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20; @@ -156,6 +162,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final HandlerCaller mCaller; private final InputMethodFileManager mFileManager; private final InputMethodAndSubtypeListManager mImListManager; + private final HardKeyboardListener mHardKeyboardListener; + private final WindowManagerService mWindowManagerService; final InputBindResult mNoBinding = new InputBindResult(null, null, -1); @@ -360,6 +368,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private AlertDialog.Builder mDialogBuilder; private AlertDialog mSwitchingDialog; + private View mSwitchingDialogTitleView; private InputMethodInfo[] mIms; private int[] mSubtypeIds; @@ -528,7 +537,31 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - public InputMethodManagerService(Context context) { + private class HardKeyboardListener + implements WindowManagerService.OnHardKeyboardStatusChangeListener { + @Override + public void onHardKeyboardStatusChange(boolean available, boolean enabled) { + mHandler.sendMessage(mHandler.obtainMessage( + MSG_HARD_KEYBOARD_SWITCH_CHANGED, available ? 1 : 0, enabled ? 1 : 0)); + } + + public void handleHardKeyboardStatusChange(boolean available, boolean enabled) { + if (DEBUG) { + Slog.w(TAG, "HardKeyboardStatusChanged: available = " + available + ", enabled = " + + enabled); + } + synchronized(mMethodMap) { + if (mSwitchingDialog != null && mSwitchingDialogTitleView != null + && mSwitchingDialog.isShowing()) { + mSwitchingDialogTitleView.findViewById( + com.android.internal.R.id.hard_keyboard_section).setVisibility( + available ? View.VISIBLE : View.GONE); + } + } + } + } + + public InputMethodManagerService(Context context, WindowManagerService windowManager) { mContext = context; mRes = context.getResources(); mHandler = new Handler(this); @@ -540,6 +573,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub handleMessage(msg); } }); + mWindowManagerService = windowManager; + mHardKeyboardListener = new HardKeyboardListener(); mImeSwitcherNotification = new Notification(); mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default; @@ -633,6 +668,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub updateImeWindowStatusLocked(); mShowOngoingImeSwitcherForPhones = mRes.getBoolean( com.android.internal.R.bool.show_ongoing_ime_switcher); + if (mShowOngoingImeSwitcherForPhones) { + mWindowManagerService.setOnHardKeyboardStatusChangeListener( + mHardKeyboardListener); + } try { startInputInnerLocked(); } catch (RuntimeException e) { @@ -1994,6 +2033,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.w(TAG, "Client died receiving input method " + args.arg2); } return true; + + // -------------------------------------------------------------- + case MSG_HARD_KEYBOARD_SWITCH_CHANGED: + mHardKeyboardListener.handleHardKeyboardStatusChange( + msg.arg1 == 1, msg.arg2 == 1); + return true; } return false; } @@ -2204,12 +2249,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } } - final TypedArray a = context.obtainStyledAttributes(null, com.android.internal.R.styleable.DialogPreference, com.android.internal.R.attr.alertDialogStyle, 0); mDialogBuilder = new AlertDialog.Builder(context) - .setTitle(com.android.internal.R.string.select_input_method) .setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { @@ -2219,6 +2262,29 @@ public class InputMethodManagerService extends IInputMethodManager.Stub .setIcon(a.getDrawable( com.android.internal.R.styleable.DialogPreference_dialogTitle)); a.recycle(); + final LayoutInflater inflater = + (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + final View tv = inflater.inflate( + com.android.internal.R.layout.input_method_switch_dialog_title, null); + mDialogBuilder.setCustomTitle(tv); + + // Setup layout for a toggle switch of the hardware keyboard + mSwitchingDialogTitleView = tv; + mSwitchingDialogTitleView.findViewById( + com.android.internal.R.id.hard_keyboard_section).setVisibility( + mWindowManagerService.isHardKeyboardAvailable() ? + View.VISIBLE : View.GONE); + final Switch hardKeySwitch = ((Switch)mSwitchingDialogTitleView.findViewById( + com.android.internal.R.id.hard_keyboard_switch)); + hardKeySwitch.setChecked(mWindowManagerService.isHardKeyboardEnabled()); + hardKeySwitch.setOnCheckedChangeListener( + new OnCheckedChangeListener() { + @Override + public void onCheckedChanged( + CompoundButton buttonView, boolean isChecked) { + mWindowManagerService.setHardKeyboardEnabled(isChecked); + } + }); final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(context, com.android.internal.R.layout.simple_list_item_2_single_choice, imList, diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java index 768be7d..a3ac8d0 100644 --- a/services/java/com/android/server/NsdService.java +++ b/services/java/com/android/server/NsdService.java @@ -32,9 +32,11 @@ import android.util.Slog; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.net.InetAddress; import java.util.ArrayList; -import java.util.concurrent.CountDownLatch; +import java.util.HashMap; import java.util.List; +import java.util.concurrent.CountDownLatch; import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.TelephonyIntents; @@ -60,10 +62,13 @@ public class NsdService extends INsdManager.Stub { /** * Clients receiving asynchronous messages */ - private List<AsyncChannel> mClients = new ArrayList<AsyncChannel>(); + private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>(); private AsyncChannel mReplyChannel = new AsyncChannel(); + private int INVALID_ID = 0; + private int mUniqueId = 1; + /** * Handles client(app) connections */ @@ -75,13 +80,19 @@ public class NsdService extends INsdManager.Stub { @Override public void handleMessage(Message msg) { + ClientInfo clientInfo; + DnsSdServiceInfo servInfo; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { AsyncChannel c = (AsyncChannel) msg.obj; if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); - mClients.add(c); + ClientInfo cInfo = new ClientInfo(c, msg.replyTo); + if (mClients.size() == 0) { + startMDnsDaemon(); + } + mClients.put(msg.replyTo, cInfo); } else { Slog.e(TAG, "Client connection failure, error=" + msg.arg1); } @@ -92,7 +103,10 @@ public class NsdService extends INsdManager.Stub { } else { if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); } - mClients.remove((AsyncChannel) msg.obj); + mClients.remove(msg.replyTo); + if (mClients.size() == 0) { + stopMDnsDaemon(); + } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: AsyncChannel ac = new AsyncChannel(); @@ -100,22 +114,98 @@ public class NsdService extends INsdManager.Stub { break; case NsdManager.DISCOVER_SERVICES: if (DBG) Slog.d(TAG, "Discover services"); - DnsSdServiceInfo s = (DnsSdServiceInfo) msg.obj; - discoverServices(1, s.getServiceType()); - mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED); + servInfo = (DnsSdServiceInfo) msg.obj; + clientInfo = mClients.get(msg.replyTo); + if (clientInfo.mDiscoveryId != INVALID_ID) { + //discovery already in progress + if (DBG) Slog.d(TAG, "discovery in progress"); + mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.ALREADY_ACTIVE); + break; + } + clientInfo.mDiscoveryId = getUniqueId(); + if (discoverServices(clientInfo.mDiscoveryId, servInfo.getServiceType())) { + mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED); + } else { + mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.ERROR); + clientInfo.mDiscoveryId = INVALID_ID; + } break; case NsdManager.STOP_DISCOVERY: if (DBG) Slog.d(TAG, "Stop service discovery"); - mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED); + clientInfo = mClients.get(msg.replyTo); + if (clientInfo.mDiscoveryId == INVALID_ID) { + //already stopped + if (DBG) Slog.d(TAG, "discovery already stopped"); + mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.ALREADY_ACTIVE); + break; + } + if (stopServiceDiscovery(clientInfo.mDiscoveryId)) { + clientInfo.mDiscoveryId = INVALID_ID; + mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); + } else { + mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, + NsdManager.ERROR); + } break; case NsdManager.REGISTER_SERVICE: if (DBG) Slog.d(TAG, "Register service"); - mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED); + clientInfo = mClients.get(msg.replyTo); + if (clientInfo.mRegisteredIds.size() >= ClientInfo.MAX_REG) { + if (DBG) Slog.d(TAG, "register service exceeds limit"); + mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.MAX_REGS_REACHED); + } + + int id = getUniqueId(); + if (registerService(id, (DnsSdServiceInfo) msg.obj)) { + clientInfo.mRegisteredIds.add(id); + } else { + mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.ERROR); + } break; case NsdManager.UPDATE_SERVICE: if (DBG) Slog.d(TAG, "Update service"); + //TODO: implement mReplyChannel.replyToMessage(msg, NsdManager.UPDATE_SERVICE_FAILED); break; + case NsdManager.RESOLVE_SERVICE: + if (DBG) Slog.d(TAG, "Resolve service"); + servInfo = (DnsSdServiceInfo) msg.obj; + clientInfo = mClients.get(msg.replyTo); + if (clientInfo.mResolveId != INVALID_ID) { + //first cancel existing resolve + stopResolveService(clientInfo.mResolveId); + } + + clientInfo.mResolveId = getUniqueId(); + if (!resolveService(clientInfo.mResolveId, servInfo)) { + mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.ERROR); + clientInfo.mResolveId = INVALID_ID; + } + break; + case NsdManager.STOP_RESOLVE: + if (DBG) Slog.d(TAG, "Stop resolve"); + clientInfo = mClients.get(msg.replyTo); + if (clientInfo.mResolveId == INVALID_ID) { + //already stopped + if (DBG) Slog.d(TAG, "resolve already stopped"); + mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, + NsdManager.ALREADY_ACTIVE); + break; + } + if (stopResolveService(clientInfo.mResolveId)) { + clientInfo.mResolveId = INVALID_ID; + mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_SUCCEEDED); + } else { + mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, + NsdManager.ERROR); + } + break; default: Slog.d(TAG, "NsdServicehandler.handleMessage ignoring msg=" + msg); break; @@ -134,12 +224,10 @@ public class NsdService extends INsdManager.Stub { nsdThread.start(); mAsyncServiceHandler = new AsyncServiceHandler(nsdThread.getLooper()); - /* mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10, MDNS_TAG, 25); Thread th = new Thread(mNativeConnector, MDNS_TAG); th.start(); - */ } public static NsdService create(Context context) throws InterruptedException { @@ -152,22 +240,29 @@ public class NsdService extends INsdManager.Stub { return new Messenger(mAsyncServiceHandler); } + private int getUniqueId() { + if (++mUniqueId == INVALID_ID) return ++mUniqueId; + return mUniqueId; + } + /* These should be in sync with system/netd/mDnsResponseCode.h */ class NativeResponseCode { - public static final int SERVICE_FOUND = 101; - public static final int SERVICE_LOST = 102; - public static final int SERVICE_DISCOVERY_FAILED = 103; + public static final int SERVICE_DISCOVERY_FAILED = 602; + public static final int SERVICE_FOUND = 603; + public static final int SERVICE_LOST = 604; - public static final int SERVICE_REGISTERED = 104; - public static final int SERVICE_REGISTRATION_FAILED = 105; + public static final int SERVICE_REGISTRATION_FAILED = 605; + public static final int SERVICE_REGISTERED = 606; - public static final int SERVICE_UPDATED = 106; - public static final int SERVICE_UPDATE_FAILED = 107; + public static final int SERVICE_RESOLUTION_FAILED = 607; + public static final int SERVICE_RESOLVED = 608; - public static final int SERVICE_RESOLVED = 108; - public static final int SERVICE_RESOLUTION_FAILED = 109; - } + public static final int SERVICE_UPDATED = 609; + public static final int SERVICE_UPDATE_FAILED = 610; + public static final int SERVICE_GET_ADDR_FAILED = 611; + public static final int SERVICE_GET_ADDR_SUCCESS = 612; + } class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks { public void onDaemonConnected() { @@ -175,21 +270,55 @@ public class NsdService extends INsdManager.Stub { } public boolean onEvent(int code, String raw, String[] cooked) { + ClientInfo clientInfo; + DnsSdServiceInfo servInfo; + int id = Integer.parseInt(cooked[1]); switch (code) { case NativeResponseCode.SERVICE_FOUND: - /* NNN uniqueId serviceName regType */ + /* NNN uniqueId serviceName regType domain */ + if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); + clientInfo = getClientByDiscovery(id); + if (clientInfo == null) break; + + servInfo = new DnsSdServiceInfo(cooked[2], cooked[3], null); + clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, servInfo); break; case NativeResponseCode.SERVICE_LOST: - /* NNN uniqueId serviceName regType */ + /* NNN uniqueId serviceName regType domain */ + if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); + clientInfo = getClientByDiscovery(id); + if (clientInfo == null) break; + + servInfo = new DnsSdServiceInfo(cooked[2], cooked[3], null); + clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, servInfo); break; case NativeResponseCode.SERVICE_DISCOVERY_FAILED: /* NNN uniqueId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); + clientInfo = getClientByDiscovery(id); + if (clientInfo == null) break; + + clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, + NsdManager.ERROR); break; case NativeResponseCode.SERVICE_REGISTERED: /* NNN regId serviceName regType */ + if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); + clientInfo = getClientByRegistration(id); + if (clientInfo == null) break; + + servInfo = new DnsSdServiceInfo(cooked[2], null, null); + clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, + id, 0, servInfo); break; case NativeResponseCode.SERVICE_REGISTRATION_FAILED: /* NNN regId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); + clientInfo = getClientByRegistration(id); + if (clientInfo == null) break; + + clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, + NsdManager.ERROR); break; case NativeResponseCode.SERVICE_UPDATED: /* NNN regId */ @@ -199,9 +328,52 @@ public class NsdService extends INsdManager.Stub { break; case NativeResponseCode.SERVICE_RESOLVED: /* NNN resolveId fullName hostName port txtlen txtdata */ + if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); + clientInfo = getClientByResolve(id); + if (clientInfo == null) break; + + int index = cooked[2].indexOf("."); + if (index == -1) { + Slog.e(TAG, "Invalid service found " + raw); + break; + } + String name = cooked[2].substring(0, index); + String rest = cooked[2].substring(index); + String type = rest.replace(".local.", ""); + + clientInfo.mResolvedService = new DnsSdServiceInfo(name, type, null); + clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); + + stopResolveService(id); + getAddrInfo(id, cooked[3]); break; case NativeResponseCode.SERVICE_RESOLUTION_FAILED: - /* NNN resovleId errorCode */ + case NativeResponseCode.SERVICE_GET_ADDR_FAILED: + /* NNN resolveId errorCode */ + if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); + clientInfo = getClientByResolve(id); + if (clientInfo == null) break; + + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.ERROR); + break; + case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: + /* NNN resolveId hostname ttl addr */ + if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); + clientInfo = getClientByResolve(id); + if (clientInfo == null || clientInfo.mResolvedService == null) break; + + try { + clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, + clientInfo.mResolvedService); + clientInfo.mResolvedService = null; + clientInfo.mResolveId = INVALID_ID; + } catch (java.net.UnknownHostException e) { + clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, + NsdManager.ERROR); + } + stopGetAddrInfo(id); break; default: break; @@ -210,48 +382,129 @@ public class NsdService extends INsdManager.Stub { } } - private void registerService(int regId, DnsSdServiceInfo service) { + private boolean startMDnsDaemon() { + if (DBG) Slog.d(TAG, "startMDnsDaemon"); + try { + mNativeConnector.execute("mdnssd", "start-service"); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to start daemon" + e); + return false; + } + return true; + } + + private boolean stopMDnsDaemon() { + if (DBG) Slog.d(TAG, "stopMDnsDaemon"); + try { + mNativeConnector.execute("mdnssd", "stop-service"); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to start daemon" + e); + return false; + } + return true; + } + + private boolean registerService(int regId, DnsSdServiceInfo service) { + if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service); try { //Add txtlen and txtdata mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(), service.getServiceType(), service.getPort()); } catch(NativeDaemonConnectorException e) { - Slog.e(TAG, "Failed to execute registerService"); + Slog.e(TAG, "Failed to execute registerService " + e); + return false; + } + return true; + } + + private boolean unregisterService(int regId) { + if (DBG) Slog.d(TAG, "unregisterService: " + regId); + try { + mNativeConnector.execute("mdnssd", "stop-register", regId); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to execute unregisterService " + e); + return false; } + return true; } - private void updateService(int regId, DnsSdTxtRecord t) { + private boolean updateService(int regId, DnsSdTxtRecord t) { + if (DBG) Slog.d(TAG, "updateService: " + regId + " " + t); try { - if (t == null) return; + if (t == null) return false; mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData()); } catch(NativeDaemonConnectorException e) { - Slog.e(TAG, "Failed to updateServices"); + Slog.e(TAG, "Failed to updateServices " + e); + return false; } + return true; } - private void discoverServices(int discoveryId, String serviceType) { + private boolean discoverServices(int discoveryId, String serviceType) { + if (DBG) Slog.d(TAG, "discoverServices: " + discoveryId + " " + serviceType); try { mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType); } catch(NativeDaemonConnectorException e) { - Slog.e(TAG, "Failed to discoverServices"); + Slog.e(TAG, "Failed to discoverServices " + e); + return false; + } + return true; + } + + private boolean stopServiceDiscovery(int discoveryId) { + if (DBG) Slog.d(TAG, "stopServiceDiscovery: " + discoveryId); + try { + mNativeConnector.execute("mdnssd", "stop-discover", discoveryId); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to stopServiceDiscovery " + e); + return false; + } + return true; + } + + private boolean resolveService(int resolveId, DnsSdServiceInfo service) { + if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service); + try { + mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(), + service.getServiceType(), "local."); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to resolveService " + e); + return false; + } + return true; + } + + private boolean stopResolveService(int resolveId) { + if (DBG) Slog.d(TAG, "stopResolveService: " + resolveId); + try { + mNativeConnector.execute("mdnssd", "stop-resolve", resolveId); + } catch(NativeDaemonConnectorException e) { + Slog.e(TAG, "Failed to stop resolve " + e); + return false; } + return true; } - private void stopServiceDiscovery(int discoveryId) { + private boolean getAddrInfo(int resolveId, String hostname) { + if (DBG) Slog.d(TAG, "getAdddrInfo: " + resolveId); try { - mNativeConnector.execute("mdnssd", "stopdiscover", discoveryId); + mNativeConnector.execute("mdnssd", "getaddrinfo", resolveId, hostname); } catch(NativeDaemonConnectorException e) { - Slog.e(TAG, "Failed to stopServiceDiscovery"); + Slog.e(TAG, "Failed to getAddrInfo " + e); + return false; } + return true; } - private void resolveService(DnsSdServiceInfo service) { + private boolean stopGetAddrInfo(int resolveId) { + if (DBG) Slog.d(TAG, "stopGetAdddrInfo: " + resolveId); try { - mNativeConnector.execute("mdnssd", "resolve", service.getServiceName(), - service.getServiceType()); + mNativeConnector.execute("mdnssd", "stop-getaddrinfo", resolveId); } catch(NativeDaemonConnectorException e) { - Slog.e(TAG, "Failed to resolveService"); + Slog.e(TAG, "Failed to stopGetAddrInfo " + e); + return false; } + return true; } @Override @@ -266,4 +519,51 @@ public class NsdService extends INsdManager.Stub { pw.println("Internal state:"); } + + private ClientInfo getClientByDiscovery(int discoveryId) { + for (ClientInfo c: mClients.values()) { + if (c.mDiscoveryId == discoveryId) { + return c; + } + } + return null; + } + + private ClientInfo getClientByResolve(int resolveId) { + for (ClientInfo c: mClients.values()) { + if (c.mResolveId == resolveId) { + return c; + } + } + return null; + } + + private ClientInfo getClientByRegistration(int regId) { + for (ClientInfo c: mClients.values()) { + if (c.mRegisteredIds.contains(regId)) { + return c; + } + } + return null; + } + + /* Information tracked per client */ + private class ClientInfo { + + private static final int MAX_REG = 5; + private AsyncChannel mChannel; + private Messenger mMessenger; + private int mDiscoveryId; + private int mResolveId; + /* Remembers a resolved service until getaddrinfo completes */ + private DnsSdServiceInfo mResolvedService; + private ArrayList<Integer> mRegisteredIds = new ArrayList<Integer>(); + + private ClientInfo(AsyncChannel c, Messenger m) { + mChannel = c; + mMessenger = m; + mDiscoveryId = mResolveId = INVALID_ID; + if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); + } + } } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 52a4110..2d2a881 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -1752,7 +1752,7 @@ public class PowerManagerService extends IPowerManager.Stub + " noChangeLights=" + noChangeLights + " reason=" + reason); } - + if (noChangeLights) { newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK); } @@ -1794,6 +1794,19 @@ public class PowerManagerService extends IPowerManager.Stub final boolean stateChanged = mPowerState != newState; + if (stateChanged && reason == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) { + if (mPolicy != null && mPolicy.isScreenSaverEnabled()) { + if (mSpew) { + Slog.d(TAG, "setPowerState: running screen saver instead of turning off screen"); + } + if (mPolicy.startScreenSaver()) { + // was successful + return; + } + } + } + + if (oldScreenOn != newScreenOn) { if (newScreenOn) { // When the user presses the power button, we need to always send out the diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 7dd736d..241d04f 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -38,6 +38,7 @@ import android.provider.Settings; import android.server.BluetoothA2dpService; import android.server.BluetoothService; import android.server.search.SearchManagerService; +import android.service.dreams.DreamManagerService; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -269,12 +270,13 @@ class ServerThread extends Thread { CountryDetectorService countryDetector = null; TextServicesManagerService tsms = null; LockSettingsService lockSettings = null; + DreamManagerService dreamy = null; // Bring up services needed for UI. if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { Slog.i(TAG, "Input Method Service"); - imm = new InputMethodManagerService(context); + imm = new InputMethodManagerService(context, wm); ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm); } catch (Throwable e) { reportWtf("starting Input Manager Service", e); @@ -613,6 +615,18 @@ class ServerThread extends Thread { } catch (Throwable e) { reportWtf("starting CommonTimeManagementService service", e); } + + if (context.getResources().getBoolean( + com.android.internal.R.bool.config_enableDreams)) { + try { + Slog.i(TAG, "Dreams Service"); + // Dreams (interactive idle-time views, a/k/a screen savers) + dreamy = new DreamManagerService(context); + ServiceManager.addService("dreams", dreamy); + } catch (Throwable e) { + reportWtf("starting DreamManagerService", e); + } + } } // Before things start rolling, be sure we have decided whether @@ -699,6 +713,7 @@ class ServerThread extends Thread { final CommonTimeManagementService commonTimeMgmtServiceF = commonTimeMgmtService; final TextServicesManagerService textServiceManagerServiceF = tsms; final StatusBarManagerService statusBarF = statusBar; + final DreamManagerService dreamyF = dreamy; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state @@ -805,6 +820,11 @@ class ServerThread extends Thread { } catch (Throwable e) { reportWtf("making Text Services Manager Service ready", e); } + try { + if (dreamyF != null) dreamyF.systemReady(); + } catch (Throwable e) { + reportWtf("making DreamManagerService ready", e); + } } }); diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java index 9b4eddc..53d1f0e 100644 --- a/services/java/com/android/server/WiredAccessoryObserver.java +++ b/services/java/com/android/server/WiredAccessoryObserver.java @@ -301,13 +301,13 @@ class WiredAccessoryObserver extends UEventObserver { // Pack up the values and broadcast them to everyone if (headset == BIT_USB_HEADSET_ANLG) { - intent = new Intent(Intent.ACTION_USB_ANLG_HEADSET_PLUG); + intent = new Intent(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra("state", state); intent.putExtra("name", headsetName); ActivityManagerNative.broadcastStickyIntent(intent, null); } else if (headset == BIT_USB_HEADSET_DGTL) { - intent = new Intent(Intent.ACTION_USB_DGTL_HEADSET_PLUG); + intent = new Intent(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra("state", state); intent.putExtra("name", headsetName); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 80e59cd..e37adc7 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -697,6 +697,16 @@ public final class ActivityManagerService extends ActivityManagerNative boolean mSleeping = false; /** + * State of external calls telling us if the device is asleep. + */ + boolean mWentToSleep = false; + + /** + * State of external call telling us if the lock screen is shown. + */ + boolean mLockScreenShown = false; + + /** * Set if we are shutting down the system, similar to sleeping. */ boolean mShuttingDown = false; @@ -3181,7 +3191,7 @@ public final class ActivityManagerService extends ActivityManagerNative } // Log the ANR to the main log. - StringBuilder info = mStringBuilder; + StringBuilder info = new StringBuilder(); info.setLength(0); info.append("ANR in ").append(app.processName); if (activity != null && activity.shortComponentName != null) { @@ -6656,17 +6666,26 @@ public final class ActivityManagerService extends ActivityManagerNative } public void goingToSleep() { + if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires permission " + + android.Manifest.permission.DEVICE_POWER); + } + synchronized(this) { - mSleeping = true; + mWentToSleep = true; mWindowManager.setEventDispatching(false); - mMainStack.stopIfSleepingLocked(); + if (!mSleeping) { + mSleeping = true; + mMainStack.stopIfSleepingLocked(); - // Initialize the wake times of all processes. - checkExcessivePowerUsageLocked(false); - mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); - Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); - mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY); + // Initialize the wake times of all processes. + checkExcessivePowerUsageLocked(false); + mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); + Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); + mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY); + } } } @@ -6726,12 +6745,40 @@ public final class ActivityManagerService extends ActivityManagerNative Binder.restoreCallingIdentity(origId); } + private void comeOutOfSleepIfNeededLocked() { + if (!mWentToSleep && !mLockScreenShown) { + if (mSleeping) { + mSleeping = false; + mMainStack.awakeFromSleepingLocked(); + mMainStack.resumeTopActivityLocked(null); + } + } + } + public void wakingUp() { + if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires permission " + + android.Manifest.permission.DEVICE_POWER); + } + synchronized(this) { + mWentToSleep = false; mWindowManager.setEventDispatching(true); - mSleeping = false; - mMainStack.awakeFromSleepingLocked(); - mMainStack.resumeTopActivityLocked(null); + comeOutOfSleepIfNeededLocked(); + } + } + + public void setLockScreenShown(boolean shown) { + if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires permission " + + android.Manifest.permission.DEVICE_POWER); + } + + synchronized(this) { + mLockScreenShown = shown; + comeOutOfSleepIfNeededLocked(); } } @@ -8309,7 +8356,7 @@ public final class ActivityManagerService extends ActivityManagerNative + android.Manifest.permission.DUMP); return; } - + boolean dumpAll = false; boolean dumpClient = false; String dumpPackage = null; @@ -8352,7 +8399,9 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println("Unknown argument: " + opt + "; use -h for help"); } } - + + long origId = Binder.clearCallingIdentity(); + boolean more = false; // Is the caller requesting to dump a particular piece of data? if (opti < args.length) { String cmd = args[opti]; @@ -8361,7 +8410,6 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { dumpActivitiesLocked(fd, pw, args, opti, true, dumpClient, null); } - return; } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) { String[] newArgs; String name; @@ -8378,7 +8426,6 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { dumpBroadcastsLocked(fd, pw, args, opti, true, name); } - return; } else if ("intents".equals(cmd) || "i".equals(cmd)) { String[] newArgs; String name; @@ -8395,7 +8442,6 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { dumpPendingIntentsLocked(fd, pw, args, opti, true, name); } - return; } else if ("processes".equals(cmd) || "p".equals(cmd)) { String[] newArgs; String name; @@ -8412,12 +8458,10 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { dumpProcessesLocked(fd, pw, args, opti, true, name); } - return; } else if ("oom".equals(cmd) || "o".equals(cmd)) { synchronized (this) { dumpOomLocked(fd, pw, args, opti, true); } - return; } else if ("provider".equals(cmd)) { String[] newArgs; String name; @@ -8434,12 +8478,10 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println("No providers match: " + name); pw.println("Use -h for help."); } - return; } else if ("providers".equals(cmd) || "prov".equals(cmd)) { synchronized (this) { dumpProvidersLocked(fd, pw, args, opti, true, null); } - return; } else if ("service".equals(cmd)) { String[] newArgs; String name; @@ -8457,13 +8499,11 @@ public final class ActivityManagerService extends ActivityManagerNative pw.println("No services match: " + name); pw.println("Use -h for help."); } - return; } else if ("package".equals(cmd)) { String[] newArgs; if (opti >= args.length) { pw.println("package: no package name specified"); pw.println("Use -h for help."); - return; } else { dumpPackage = args[opti]; opti++; @@ -8472,22 +8512,25 @@ public final class ActivityManagerService extends ActivityManagerNative args.length - opti); args = newArgs; opti = 0; + more = true; } } else if ("services".equals(cmd) || "s".equals(cmd)) { synchronized (this) { dumpServicesLocked(fd, pw, args, opti, true, dumpClient, null); } - return; } else { // Dumping a single activity? if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) { pw.println("Bad activity command, or no activities match: " + cmd); pw.println("Use -h for help."); } + } + if (!more) { + Binder.restoreCallingIdentity(origId); return; } } - + // No piece of data specified, dump everything. synchronized (this) { boolean needSep; @@ -8528,8 +8571,9 @@ public final class ActivityManagerService extends ActivityManagerNative } dumpProcessesLocked(fd, pw, args, opti, dumpAll, dumpPackage); } + Binder.restoreCallingIdentity(origId); } - + boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) { pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)"); @@ -8818,7 +8862,13 @@ public final class ActivityManagerService extends ActivityManagerNative } } } - pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown); + if (mSleeping || mWentToSleep || mLockScreenShown) { + pw.println(" mSleeping=" + mSleeping + " mWentToSleep=" + mWentToSleep + + " mLockScreenShown " + mLockScreenShown); + } + if (mShuttingDown) { + pw.println(" mShuttingDown=" + mShuttingDown); + } if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient || mOrigWaitForDebugger) { pw.println(" mDebugApp=" + mDebugApp + "/orig=" + mOrigDebugApp @@ -13444,7 +13494,7 @@ public final class ActivityManagerService extends ActivityManagerNative // an earlier hidden adjustment that isn't really for us... if // so, use the new hidden adjustment. if (!recursed && app.hidden) { - app.curAdj = app.curRawAdj = hiddenAdj; + app.curAdj = app.curRawAdj = app.nonStoppingAdj = hiddenAdj; } return app.curRawAdj; } @@ -13468,7 +13518,7 @@ public final class ActivityManagerService extends ActivityManagerNative // below foreground, so it is not worth doing work for it. app.adjType = "fixed"; app.adjSeq = mAdjSeq; - app.curRawAdj = app.maxAdj; + app.curRawAdj = app.nonStoppingAdj = app.maxAdj; app.foregroundActivities = false; app.keeping = true; app.curSchedGroup = Process.THREAD_GROUP_DEFAULT; @@ -13545,6 +13595,8 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjType = "bg-empty"; } + boolean hasStoppingActivities = false; + // Examine all activities if not already foreground. if (!app.foregroundActivities && activitiesSize > 0) { for (int j = 0; j < activitiesSize; j++) { @@ -13559,15 +13611,20 @@ public final class ActivityManagerService extends ActivityManagerNative app.hidden = false; app.foregroundActivities = true; break; - } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED - || r.state == ActivityState.STOPPING) { - // Only upgrade adjustment. + } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) { if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; - app.adjType = "stopping"; + app.adjType = "pausing"; } app.hidden = false; app.foregroundActivities = true; + } else if (r.state == ActivityState.STOPPING) { + // We will apply the actual adjustment later, because + // we want to allow this process to immediately go through + // any memory trimming that is in effect. + app.hidden = false; + app.foregroundActivities = true; + hasStoppingActivities = true; } } } @@ -13625,7 +13682,7 @@ public final class ActivityManagerService extends ActivityManagerNative // this gives us a baseline and makes sure we don't get into an // infinite recursion. app.adjSeq = mAdjSeq; - app.curRawAdj = adj; + app.curRawAdj = app.nonStoppingAdj = adj; if (mBackupTarget != null && app == mBackupTarget.app) { // If possible we want to avoid killing apps while they're being backed up @@ -13882,6 +13939,28 @@ public final class ActivityManagerService extends ActivityManagerNative } } + if (adj == ProcessList.SERVICE_ADJ) { + if (doingAll) { + app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3); + mNewNumServiceProcs++; + } + if (app.serviceb) { + adj = ProcessList.SERVICE_B_ADJ; + } + } else { + app.serviceb = false; + } + + app.nonStoppingAdj = adj; + + if (hasStoppingActivities) { + // Only upgrade adjustment. + if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { + adj = ProcessList.PERCEPTIBLE_APP_ADJ; + app.adjType = "stopping"; + } + } + app.curRawAdj = adj; //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid + @@ -13915,18 +13994,6 @@ public final class ActivityManagerService extends ActivityManagerNative } } - if (adj == ProcessList.SERVICE_ADJ) { - if (doingAll) { - app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3); - mNewNumServiceProcs++; - } - if (app.serviceb) { - adj = ProcessList.SERVICE_B_ADJ; - } - } else { - app.serviceb = false; - } - app.curAdj = adj; app.curSchedGroup = schedGroup; @@ -14138,7 +14205,7 @@ public final class ActivityManagerService extends ActivityManagerNative } // If a process has held a wake lock for more // than 50% of the time during this period, - // that sounds pad. Kill! + // that sounds bad. Kill! if (doWakeKills && realtimeSince > 0 && ((wtimeUsed*100)/realtimeSince) >= 50) { synchronized (stats) { @@ -14186,23 +14253,6 @@ public final class ActivityManagerService extends ActivityManagerNative computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll); if (app.curRawAdj != app.setRawAdj) { - if (false) { - // Removing for now. Forcing GCs is not so useful anymore - // with Dalvik, and the new memory level hint facility is - // better for what we need to do these days. - if (app.curRawAdj > ProcessList.FOREGROUND_APP_ADJ - && app.setRawAdj <= ProcessList.FOREGROUND_APP_ADJ) { - // If this app is transitioning from foreground to - // non-foreground, have it do a gc. - scheduleAppGcLocked(app); - } else if (app.curRawAdj >= ProcessList.HIDDEN_APP_MIN_ADJ - && app.setRawAdj < ProcessList.HIDDEN_APP_MIN_ADJ) { - // Likewise do a gc when an app is moving in to the - // background (such as a service stopping). - scheduleAppGcLocked(app); - } - } - if (wasKeeping && !app.keeping) { // This app is no longer something we want to keep. Note // its current wake lock time to later know to kill it if @@ -14319,6 +14369,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (factor < 1) factor = 1; int step = 0; int numHidden = 0; + int numTrimming = 0; // First update the OOM adjustment for each of the // application processes based on their current state. @@ -14363,6 +14414,11 @@ public final class ActivityManagerService extends ActivityManagerNative app.killedBackground = true; Process.killProcessQuiet(app.pid); } + if (app.nonStoppingAdj >= ProcessList.HOME_APP_ADJ + && app.nonStoppingAdj != ProcessList.SERVICE_B_ADJ + && !app.killedBackground) { + numTrimming++; + } } } @@ -14376,7 +14432,7 @@ public final class ActivityManagerService extends ActivityManagerNative // memory they want. if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/2)) { final int N = mLruProcesses.size(); - factor = numHidden/3; + factor = numTrimming/3; int minFactor = 2; if (mHomeProcess != null) minFactor++; if (mPreviousProcess != null) minFactor++; @@ -14393,8 +14449,8 @@ public final class ActivityManagerService extends ActivityManagerNative int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; for (i=0; i<N; i++) { ProcessRecord app = mLruProcesses.get(i); - if (app.curAdj >= ProcessList.HOME_APP_ADJ - && app.curAdj != ProcessList.SERVICE_B_ADJ + if (app.nonStoppingAdj >= ProcessList.HOME_APP_ADJ + && app.nonStoppingAdj != ProcessList.SERVICE_B_ADJ && !app.killedBackground) { if (app.trimMemoryLevel < curLevel && app.thread != null) { try { @@ -14426,7 +14482,7 @@ public final class ActivityManagerService extends ActivityManagerNative break; } } - } else if (app.curAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) { + } else if (app.nonStoppingAdj == ProcessList.HEAVY_WEIGHT_APP_ADJ) { if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND && app.thread != null) { try { @@ -14437,7 +14493,7 @@ public final class ActivityManagerService extends ActivityManagerNative } app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; } else { - if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi) + if ((app.nonStoppingAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi) && app.pendingUiClean) { // If this application is now in the background and it // had done UI, then give it the special trim level to @@ -14464,7 +14520,7 @@ public final class ActivityManagerService extends ActivityManagerNative final int N = mLruProcesses.size(); for (i=0; i<N; i++) { ProcessRecord app = mLruProcesses.get(i); - if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi) + if ((app.nonStoppingAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi) && app.pendingUiClean) { if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN && app.thread != null) { diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a01ed25..6596e1f 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -97,6 +97,11 @@ final class ActivityStack { // next activity. static final int PAUSE_TIMEOUT = 500; + // How long we wait for the activity to tell us it has stopped before + // giving up. This is a good amount of time because we really need this + // from the application in order to get its saved state. + static final int STOP_TIMEOUT = 10*1000; + // How long we can hold the sleep wake lock before giving up. static final int SLEEP_TIMEOUT = 5*1000; @@ -280,6 +285,7 @@ final class ActivityStack { static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5; static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6; static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7; + static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 8; final Handler mHandler = new Handler() { //public Handler() { @@ -364,6 +370,17 @@ final class ActivityStack { resumeTopActivityLocked(null); } } break; + case STOP_TIMEOUT_MSG: { + ActivityRecord r = (ActivityRecord)msg.obj; + // We don't at this point know if the activity is fullscreen, + // so we need to be conservative and assume it isn't. + Slog.w(TAG, "Activity stop timeout for " + r); + synchronized (mService) { + if (r.isInHistory()) { + activityStoppedLocked(r, null, null, null); + } + } + } break; } } }; @@ -1000,31 +1017,38 @@ final class ActivityStack { final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail, CharSequence description) { if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle); - r.icicle = icicle; - r.haveState = true; - r.updateThumbnail(thumbnail, description); - r.stopped = true; - if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)"); - r.state = ActivityState.STOPPED; - if (!r.finishing) { - if (r.configDestroy) { - destroyActivityLocked(r, true, false, "stop-config"); - resumeTopActivityLocked(null); - } else { - // Now that this process has stopped, we may want to consider - // it to be the previous app to try to keep around in case - // the user wants to return to it. - ProcessRecord fgApp = null; - if (mResumedActivity != null) { - fgApp = mResumedActivity.app; - } else if (mPausingActivity != null) { - fgApp = mPausingActivity.app; - } - if (r.app != null && fgApp != null && r.app != fgApp - && r.lastVisibleTime > mService.mPreviousProcessVisibleTime - && r.app != mService.mHomeProcess) { - mService.mPreviousProcess = r.app; - mService.mPreviousProcessVisibleTime = r.lastVisibleTime; + if (icicle != null) { + // If icicle is null, this is happening due to a timeout, so we + // haven't really saved the state. + r.icicle = icicle; + r.haveState = true; + r.updateThumbnail(thumbnail, description); + } + if (!r.stopped) { + if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)"); + mHandler.removeMessages(STOP_TIMEOUT_MSG, r); + r.stopped = true; + r.state = ActivityState.STOPPED; + if (!r.finishing) { + if (r.configDestroy) { + destroyActivityLocked(r, true, false, "stop-config"); + resumeTopActivityLocked(null); + } else { + // Now that this process has stopped, we may want to consider + // it to be the previous app to try to keep around in case + // the user wants to return to it. + ProcessRecord fgApp = null; + if (mResumedActivity != null) { + fgApp = mResumedActivity.app; + } else if (mPausingActivity != null) { + fgApp = mPausingActivity.app; + } + if (r.app != null && fgApp != null && r.app != fgApp + && r.lastVisibleTime > mService.mPreviousProcessVisibleTime + && r.app != mService.mHomeProcess) { + mService.mPreviousProcess = r.app; + mService.mPreviousProcessVisibleTime = r.lastVisibleTime; + } } } } @@ -3228,6 +3252,9 @@ final class ActivityStack { if (mService.isSleeping()) { r.setSleeping(true); } + Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG); + msg.obj = r; + mHandler.sendMessageDelayed(msg, STOP_TIMEOUT); } catch (Exception e) { // Maybe just ignore exceptions here... if the process // has crashed, our death notification will clean things @@ -3694,6 +3721,7 @@ final class ActivityStack { // Get rid of any pending idle timeouts. mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); + mHandler.removeMessages(STOP_TIMEOUT_MSG, r); mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); r.finishLaunchTickingLocked(); diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index b64261d..4529ecc 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -63,6 +63,7 @@ class ProcessRecord { int hiddenAdj; // If hidden, this is the adjustment to use int curRawAdj; // Current OOM unlimited adjustment for this process int setRawAdj; // Last set OOM unlimited adjustment for this process + int nonStoppingAdj; // Adjustment not counting any stopping activities int curAdj; // Current OOM adjustment for this process int setAdj; // Last set OOM adjustment for this process int curSchedGroup; // Currently desired scheduling class @@ -199,6 +200,7 @@ class ProcessRecord { pw.print(" hidden="); pw.print(hiddenAdj); pw.print(" curRaw="); pw.print(curRawAdj); pw.print(" setRaw="); pw.print(setRawAdj); + pw.print(" nonStopping="); pw.print(nonStoppingAdj); pw.print(" cur="); pw.print(curAdj); pw.print(" set="); pw.println(setAdj); pw.print(prefix); pw.print("curSchedGroup="); pw.print(curSchedGroup); diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index b8cc65e..2f25df1 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -18,37 +18,45 @@ package com.android.server.input; import com.android.internal.util.XmlUtils; import com.android.server.Watchdog; -import com.android.server.input.InputFilter.Host; -import com.android.server.wm.WindowManagerService; import org.xmlpull.v1.XmlPullParser; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; import android.database.ContentObserver; import android.hardware.input.IInputManager; import android.hardware.input.InputManager; +import android.hardware.input.KeyboardLayout; import android.os.Binder; +import android.os.Bundle; import android.os.Environment; import android.os.Handler; -import android.os.Looper; import android.os.MessageQueue; import android.os.Process; -import android.os.SystemProperties; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; +import android.util.Log; import android.util.Slog; import android.util.Xml; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; +import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.PointerIcon; import android.view.Surface; import android.view.ViewConfiguration; -import android.view.WindowManager; import android.view.WindowManagerPolicy; +import android.view.KeyCharacterMap.UnavailableException; import java.io.File; import java.io.FileDescriptor; @@ -57,6 +65,8 @@ import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; /* * Wraps the C++ InputManager and provides its callbacks. @@ -135,6 +145,10 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. /** The key is down but is a virtual key press that is being emulated by the system. */ public static final int KEY_STATE_VIRTUAL = 2; + // Used to simulate a persistent data store for keyboard layouts. + // TODO: Replace with the real thing. + private final HashMap<String, String> mFakeRegistry = new HashMap<String, String>(); + // State for the currently installed input filter. final Object mInputFilterLock = new Object(); InputFilter mInputFilter; @@ -246,7 +260,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. * key codes. * @return True if the lookup was successful, false otherwise. */ - @Override + @Override // Binder call public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) { if (keyCodes == null) { throw new IllegalArgumentException("keyCodes must not be null."); @@ -337,7 +351,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. } } - @Override + @Override // Binder call public boolean injectInputEvent(InputEvent event, int mode) { if (event == null) { throw new IllegalArgumentException("event must not be null"); @@ -380,7 +394,7 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. * @param id The device id. * @return The input device or null if not found. */ - @Override + @Override // Binder call public InputDevice getInputDevice(int deviceId) { return nativeGetInputDevice(mPtr, deviceId); } @@ -389,11 +403,187 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. * Gets the ids of all input devices in the system. * @return The input device ids. */ - @Override + @Override // Binder call public int[] getInputDeviceIds() { return nativeGetInputDeviceIds(mPtr); } - + + @Override // Binder call + public KeyboardLayout[] getKeyboardLayouts() { + ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>(); + + final PackageManager pm = mContext.getPackageManager(); + Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS); + for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent, + PackageManager.GET_META_DATA)) { + loadKeyboardLayouts(pm, resolveInfo.activityInfo, list, null); + } + return list.toArray(new KeyboardLayout[list.size()]); + } + + @Override // Binder call + public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) { + if (keyboardLayoutDescriptor == null) { + throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null"); + } + + KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor); + if (d == null) { + return null; + } + + final PackageManager pm = mContext.getPackageManager(); + try { + ActivityInfo receiver = pm.getReceiverInfo( + new ComponentName(d.packageName, d.receiverName), + PackageManager.GET_META_DATA); + return loadKeyboardLayouts(pm, receiver, null, d.keyboardLayoutName); + } catch (NameNotFoundException ex) { + Log.w(TAG, "Could not load keyboard layout '" + d.keyboardLayoutName + + "' from receiver " + d.packageName + "/" + d.receiverName, ex); + return null; + } + } + + private KeyboardLayout loadKeyboardLayouts( + PackageManager pm, ActivityInfo receiver, + List<KeyboardLayout> list, String keyboardName) { + Bundle metaData = receiver.metaData; + if (metaData == null) { + return null; + } + + int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS); + if (configResId == 0) { + Log.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS + + "' on receiver " + receiver.packageName + "/" + receiver.name); + return null; + } + + try { + Resources resources = pm.getResourcesForApplication(receiver.applicationInfo); + XmlResourceParser parser = resources.getXml(configResId); + try { + XmlUtils.beginDocument(parser, "keyboard-layouts"); + + for (;;) { + XmlUtils.nextElement(parser); + String element = parser.getName(); + if (element == null) { + break; + } + if (element.equals("keyboard-layout")) { + TypedArray a = resources.obtainAttributes( + parser, com.android.internal.R.styleable.KeyboardLayout); + try { + String name = a.getString( + com.android.internal.R.styleable.KeyboardLayout_name); + String label = a.getString( + com.android.internal.R.styleable.KeyboardLayout_label); + int kcmResId = a.getResourceId( + com.android.internal.R.styleable.KeyboardLayout_kcm, 0); + if (name == null || label == null || kcmResId == 0) { + Log.w(TAG, "Missing required 'name', 'label' or 'kcm' " + + "attributes in keyboard layout " + + "resource from receiver " + + receiver.packageName + "/" + receiver.name); + } else { + String descriptor = KeyboardLayoutDescriptor.format( + receiver.packageName, receiver.name, name); + KeyboardLayout c = new KeyboardLayout(descriptor, label); + if (keyboardName != null && name.equals(keyboardName)) { + return c; + } + if (list != null) { + list.add(c); + } + } + } finally { + a.recycle(); + } + } else { + Log.w(TAG, "Skipping unrecognized element '" + element + + "' in keyboard layout resource from receiver " + + receiver.packageName + "/" + receiver.name); + } + } + } finally { + parser.close(); + } + } catch (Exception ex) { + Log.w(TAG, "Could not load keyboard layout resource from receiver " + + receiver.packageName + "/" + receiver.name, ex); + return null; + } + if (keyboardName != null) { + Log.w(TAG, "Could not load keyboard layout '" + keyboardName + + "' from receiver " + receiver.packageName + "/" + receiver.name + + " because it was not declared in the keyboard layout resource."); + } + return null; + } + + @Override // Binder call + public String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor) { + if (inputDeviceDescriptor == null) { + throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); + } + + return mFakeRegistry.get(inputDeviceDescriptor); + } + + @Override // Binder call + public void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor, + String keyboardLayoutDescriptor) { + if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT, + "setKeyboardLayoutForInputDevice()")) { + throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission"); + } + + if (inputDeviceDescriptor == null) { + throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); + } + + mFakeRegistry.put(inputDeviceDescriptor, keyboardLayoutDescriptor); + } + + /** + * Loads the key character map associated with the keyboard layout. + * + * @param pm The package manager. + * @return The key character map, or null if it could not be loaded for any reason. + * + public KeyCharacterMap loadKeyCharacterMap(PackageManager pm) { + if (pm == null) { + throw new IllegalArgumentException("pm must not be null"); + } + + if (mKeyCharacterMap == null) { + KeyboardLayoutDescriptor d = InputManager.parseKeyboardLayoutDescriptor(mDescriptor); + if (d == null) { + Log.e(InputManager.TAG, "Could not load key character map '" + mDescriptor + + "' because the descriptor could not be parsed."); + return null; + } + + CharSequence cs = pm.getText(d.packageName, mKeyCharacterMapResId, null); + if (cs == null) { + Log.e(InputManager.TAG, "Could not load key character map '" + mDescriptor + + "' because its associated resource could not be loaded."); + return null; + } + + try { + mKeyCharacterMap = KeyCharacterMap.load(cs); + } catch (UnavailableException ex) { + Log.e(InputManager.TAG, "Could not load key character map '" + mDescriptor + + "' due to an error while parsing.", ex); + return null; + } + } + return mKeyCharacterMap; + }*/ + public void setInputWindows(InputWindowHandle[] windowHandles) { nativeSetInputWindows(mPtr, windowHandles); } @@ -433,18 +623,17 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. return nativeTransferTouchFocus(mPtr, fromChannel, toChannel); } - /** - * Set the pointer speed. - * @param speed The pointer speed as a value between -7 (slowest) and 7 (fastest) - * where 0 is the default speed. - */ - @Override + @Override // Binder call public void tryPointerSpeed(int speed) { if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED, "tryPointerSpeed()")) { throw new SecurityException("Requires SET_POINTER_SPEED permission"); } + if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) { + throw new IllegalArgumentException("speed out of range"); + } + setPointerSpeedUnchecked(speed); } @@ -740,4 +929,32 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. } } } + + private static final class KeyboardLayoutDescriptor { + public String packageName; + public String receiverName; + public String keyboardLayoutName; + + public static String format(String packageName, + String receiverName, String keyboardName) { + return packageName + "/" + receiverName + "/" + keyboardName; + } + + public static KeyboardLayoutDescriptor parse(String descriptor) { + int pos = descriptor.indexOf('/'); + if (pos < 0 || pos + 1 == descriptor.length()) { + return null; + } + int pos2 = descriptor.indexOf('/', pos + 1); + if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) { + return null; + } + + KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor(); + result.packageName = descriptor.substring(0, pos); + result.receiverName = descriptor.substring(pos + 1, pos2); + result.keyboardLayoutName = descriptor.substring(pos2 + 1); + return result; + } + } } diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 77addd6..fa62e49 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -1588,7 +1588,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } private Handler.Callback mHandlerCallback = new Handler.Callback() { - /** {@inheritDoc} */ + @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_RULES_CHANGED: { diff --git a/services/java/com/android/server/net/NetworkStatsCollection.java b/services/java/com/android/server/net/NetworkStatsCollection.java index 70038d9..2892a74 100644 --- a/services/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/java/com/android/server/net/NetworkStatsCollection.java @@ -57,8 +57,6 @@ import libcore.io.IoUtils; * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. */ public class NetworkStatsCollection implements FileRotator.Reader { - private static final String TAG = "NetworkStatsCollection"; - /** File header magic number: "ANET" */ private static final int FILE_MAGIC = 0x414E4554; @@ -173,7 +171,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { } /** - * Record given {@link NetworkStats.Entry} into this collection. + * Record given {@link android.net.NetworkStats.Entry} into this collection. */ public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start, long end, NetworkStats.Entry entry) { @@ -227,7 +225,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } - /** {@inheritDoc} */ + @Override public void read(InputStream in) throws IOException { read(new DataInputStream(in)); } @@ -502,7 +500,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { return false; } - /** {@inheritDoc} */ + @Override public int compareTo(Key another) { return Integer.compare(uid, another.uid); } diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java index 540f606..57ad158 100644 --- a/services/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/java/com/android/server/net/NetworkStatsRecorder.java @@ -240,22 +240,22 @@ public class NetworkStatsRecorder { mCollection = checkNotNull(collection, "missing NetworkStatsCollection"); } - /** {@inheritDoc} */ + @Override public void reset() { // ignored } - /** {@inheritDoc} */ + @Override public void read(InputStream in) throws IOException { mCollection.read(in); } - /** {@inheritDoc} */ + @Override public boolean shouldWrite() { return true; } - /** {@inheritDoc} */ + @Override public void write(OutputStream out) throws IOException { mCollection.write(new DataOutputStream(out)); mCollection.reset(); @@ -275,24 +275,24 @@ public class NetworkStatsRecorder { mUid = uid; } - /** {@inheritDoc} */ + @Override public void reset() { mTemp.reset(); } - /** {@inheritDoc} */ + @Override public void read(InputStream in) throws IOException { mTemp.read(in); mTemp.clearDirty(); mTemp.removeUid(mUid); } - /** {@inheritDoc} */ + @Override public boolean shouldWrite() { return mTemp.isDirty(); } - /** {@inheritDoc} */ + @Override public void write(OutputStream out) throws IOException { mTemp.write(new DataOutputStream(out)); } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index f7ba329..4382a03 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -500,6 +500,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Binder.restoreCallingIdentity(token); } + // splice in operation counts + networkLayer.spliceOperationsFrom(mUidOperations); + final NetworkStats dataLayer = new NetworkStats( networkLayer.getElapsedRealtime(), networkLayer.size()); @@ -510,8 +513,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { dataLayer.combineValues(entry); } - // splice in operation counts - dataLayer.spliceOperationsFrom(mUidOperations); return dataLayer; } @@ -998,7 +999,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private Handler.Callback mHandlerCallback = new Handler.Callback() { - /** {@inheritDoc} */ + @Override public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_PERFORM_POLL: { @@ -1037,7 +1038,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> { - /** {@inheritDoc} */ + @Override public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, String cookie) { Log.w(TAG, "found non-monotonic values; saving to dropbox"); @@ -1056,7 +1057,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Default external settings that read from {@link Settings.Secure}. + * Default external settings that read from + * {@link android.provider.Settings.Secure}. */ private static class DefaultNetworkStatsSettings implements NetworkStatsSettings { private final ContentResolver mResolver; @@ -1074,19 +1076,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return Settings.Secure.getInt(mResolver, name, defInt) != 0; } + @Override public long getPollInterval() { return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); } + @Override public long getTimeCacheMaxAge() { return getSecureLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS); } + @Override public long getGlobalAlertBytes() { return getSecureLong(NETSTATS_GLOBAL_ALERT_BYTES, 2 * MB_IN_BYTES); } + @Override public boolean getSampleEnabled() { return getSecureBoolean(NETSTATS_SAMPLE_ENABLED, true); } + @Override public Config getDevConfig() { return new Config(getSecureLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getSecureLong(NETSTATS_DEV_PERSIST_BYTES, 2 * MB_IN_BYTES), @@ -1094,6 +1101,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { getSecureLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS)); } + @Override public Config getUidConfig() { return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), getSecureLong(NETSTATS_UID_PERSIST_BYTES, 2 * MB_IN_BYTES), @@ -1101,6 +1109,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { getSecureLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS)); } + @Override public Config getUidTagConfig() { return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), getSecureLong(NETSTATS_UID_PERSIST_BYTES, 2 * MB_IN_BYTES), diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java index bb7f4fc..bb73b29 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/java/com/android/server/pm/Settings.java @@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; import static android.content.pm.PackageManager.ENFORCEMENT_DEFAULT; +import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.JournaledFile; @@ -2558,9 +2559,13 @@ final class Settings { if (p.perm != null) { pw.print(" perm="); pw.println(p.perm); } + if (READ_EXTERNAL_STORAGE.equals(p.name)) { + pw.print(" enforcement="); + pw.println(PackageManager.enforcementToString(mReadExternalStorageEnforcement)); + } } } - + void dumpSharedUsersLPr(PrintWriter pw, String packageName, DumpState dumpState) { boolean printedSomething = false; for (SharedUserSetting su : mSharedUsers.values()) { diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java index e460f7f..3dcfd3c 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java @@ -33,6 +33,7 @@ class ScreenRotationAnimation { static final String TAG = "ScreenRotationAnimation"; static final boolean DEBUG_STATE = false; static final boolean DEBUG_TRANSFORMS = false; + static final boolean TWO_PHASE_ANIMATION = false; static final boolean USE_CUSTOM_BLACK_FRAME = false; static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200; @@ -44,7 +45,6 @@ class ScreenRotationAnimation { BlackFrame mEnteringBlackFrame; int mWidth, mHeight; - int mSnapshotDeltaRotation; int mOriginalRotation; int mOriginalWidth, mOriginalHeight; int mCurRotation; @@ -138,10 +138,9 @@ class ScreenRotationAnimation { if (mEnteringBlackFrame != null) { mEnteringBlackFrame.printTo(prefix + " ", pw); } - pw.print(prefix); pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation); - pw.print(" mCurRotation="); pw.println(mCurRotation); - pw.print(prefix); pw.print("mOriginalRotation="); pw.print(mOriginalRotation); - pw.print(" mOriginalWidth="); pw.print(mOriginalWidth); + pw.print(prefix); pw.print("mCurRotation="); pw.print(mCurRotation); + pw.print(" mOriginalRotation="); pw.println(mOriginalRotation); + pw.print(prefix); pw.print("mOriginalWidth="); pw.print(mOriginalWidth); pw.print(" mOriginalHeight="); pw.println(mOriginalHeight); pw.print(prefix); pw.print("mStarted="); pw.print(mStarted); pw.print(" mAnimRunning="); pw.print(mAnimRunning); @@ -306,8 +305,13 @@ class ScreenRotationAnimation { public boolean setRotation(int rotation, SurfaceSession session, long maxAnimationDuration, float animationScale, int finalWidth, int finalHeight) { setRotation(rotation); - return startAnimation(session, maxAnimationDuration, animationScale, - finalWidth, finalHeight, false); + if (TWO_PHASE_ANIMATION) { + return startAnimation(session, maxAnimationDuration, animationScale, + finalWidth, finalHeight, false); + } else { + // Don't start animation yet. + return false; + } } /** @@ -330,7 +334,8 @@ class ScreenRotationAnimation { // Figure out how the screen has moved from the original rotation. int delta = deltaRotation(mCurRotation, mOriginalRotation); - if (mFinishExitAnimation == null && (!dismissing || delta != Surface.ROTATION_0)) { + if (TWO_PHASE_ANIMATION && mFinishExitAnimation == null + && (!dismissing || delta != Surface.ROTATION_0)) { if (DEBUG_STATE) Slog.v(TAG, "Creating start and finish animations"); firstStart = true; mStartExitAnimation = AnimationUtils.loadAnimation(mContext, @@ -406,7 +411,7 @@ class ScreenRotationAnimation { // means to allow supplying the last and next size. In this definition // "%p" is the original (let's call it "previous") size, and "%" is the // screen's current/new size. - if (firstStart) { + if (TWO_PHASE_ANIMATION && firstStart) { if (DEBUG_STATE) Slog.v(TAG, "Initializing start and finish animations"); mStartEnterAnimation.initialize(finalWidth, finalHeight, halfWidth, halfHeight); @@ -433,7 +438,7 @@ class ScreenRotationAnimation { mFinishAnimReady = false; mFinishAnimStartTime = -1; - if (firstStart) { + if (TWO_PHASE_ANIMATION && firstStart) { mStartExitAnimation.restrictDuration(maxAnimationDuration); mStartExitAnimation.scaleCurrentDuration(animationScale); mStartEnterAnimation.restrictDuration(maxAnimationDuration); @@ -624,6 +629,14 @@ class ScreenRotationAnimation { } public boolean isAnimating() { + if (TWO_PHASE_ANIMATION) { + return hasAnimations() || mFinishAnimReady; + } else { + return hasAnimations(); + } + } + + private boolean hasAnimations() { return mStartEnterAnimation != null || mStartExitAnimation != null || mStartFrameAnimation != null || mFinishEnterAnimation != null || mFinishExitAnimation != null @@ -633,7 +646,6 @@ class ScreenRotationAnimation { } private boolean stepAnimation(long now) { - if (mFinishAnimReady && mFinishAnimStartTime < 0) { if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready"); mFinishAnimStartTime = now; @@ -794,6 +806,10 @@ class ScreenRotationAnimation { } void updateSurfaces() { + if (!mStarted) { + return; + } + if (mSurface != null) { if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) { if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface"); @@ -834,7 +850,7 @@ class ScreenRotationAnimation { } public boolean stepAnimationLocked(long now) { - if (!isAnimating()) { + if (!hasAnimations()) { if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running"); mFinishAnimReady = false; return false; diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 0d64b68..fa009eb 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -22,6 +22,7 @@ import android.view.animation.Animation; import com.android.internal.policy.impl.PhoneWindowManager; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.HashSet; /** @@ -158,9 +159,7 @@ public class WindowAnimator { } } - if (mScreenRotationAnimation != null && - (mScreenRotationAnimation.isAnimating() || - mScreenRotationAnimation.mFinishAnimReady)) { + if (mScreenRotationAnimation != null && mScreenRotationAnimation.isAnimating()) { if (mScreenRotationAnimation.stepAnimationLocked(mCurrentTime)) { mAnimating = true; } else { @@ -174,6 +173,9 @@ public class WindowAnimator { private void updateWindowsAndWallpaperLocked() { ++mTransactionSequence; + ArrayList<WindowStateAnimator> unForceHiding = null; + boolean wallpaperInUnForceHiding = false; + for (int i = mService.mWindows.size() - 1; i >= 0; i--) { WindowState win = mService.mWindows.get(i); WindowStateAnimator winAnimator = win.mWinAnimator; @@ -269,13 +271,12 @@ public class WindowAnimator { if (changed) { if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0 && win.isVisibleNow() /*w.isReadyForDisplay()*/) { - // Assume we will need to animate. If - // we don't (because the wallpaper will - // stay with the lock screen), then we will - // clean up later. - Animation a = mPolicy.createForceHideEnterAnimation(); - if (a != null) { - winAnimator.setAnimation(a); + if (unForceHiding == null) { + unForceHiding = new ArrayList<WindowStateAnimator>(); + } + unForceHiding.add(winAnimator); + if ((win.mAttrs.flags&WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { + wallpaperInUnForceHiding = true; } } if (mCurrentFocus == null || mCurrentFocus.mLayer < win.mLayer) { @@ -358,6 +359,17 @@ public class WindowAnimator { } } } // end forall windows + + // If we have windows that are being show due to them no longer + // being force-hidden, apply the appropriate animation to them. + if (unForceHiding != null) { + for (int i=unForceHiding.size()-1; i>=0; i--) { + Animation a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding); + if (a != null) { + unForceHiding.get(i).setAnimation(a); + } + } + } } private void testTokenMayBeDrawnLocked() { @@ -453,7 +465,7 @@ public class WindowAnimator { mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime); } if (mDimAnimator != null && mDimAnimator.mDimShown) { - mAnimating |= mDimAnimator.updateSurface(mDimParams != null, mCurrentTime, + mAnimating |= mDimAnimator.updateSurface(isDimming(), mCurrentTime, !mService.okToDisplay()); } @@ -471,9 +483,7 @@ public class WindowAnimator { Surface.closeTransaction(); } - if (mBulkUpdateParams != 0) { - mService.bulkSetParameters(mBulkUpdateParams); - } + mService.bulkSetParameters(mBulkUpdateParams); } WindowState mCurrentFocus; @@ -503,6 +513,10 @@ public class WindowAnimator { mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null)); } + boolean isDimming() { + return mDimParams != null; + } + public void dump(PrintWriter pw, String prefix, boolean dumpAll) { if (mWindowDetachedWallpaper != null) { pw.print(" mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper); diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 6f7852d..b0e017f 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -28,6 +28,7 @@ import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManager.LayoutParams.TYPE_DREAM; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; @@ -2131,6 +2132,11 @@ public class WindowManagerService extends IWindowManager.Stub + attrs.token + ". Aborting."); return WindowManagerImpl.ADD_BAD_APP_TOKEN; } + if (attrs.type == TYPE_DREAM) { + Slog.w(TAG, "Attempted to add Dream window with unknown token " + + attrs.token + ". Aborting."); + return WindowManagerImpl.ADD_BAD_APP_TOKEN; + } token = new WindowToken(this, attrs.token, -1, false); addToken = true; } else if (attrs.type >= FIRST_APPLICATION_WINDOW @@ -2163,6 +2169,12 @@ public class WindowManagerService extends IWindowManager.Stub + attrs.token + ". Aborting."); return WindowManagerImpl.ADD_BAD_APP_TOKEN; } + } else if (attrs.type == TYPE_DREAM) { + if (token.windowType != TYPE_DREAM) { + Slog.w(TAG, "Attempted to add Dream window with bad token " + + attrs.token + ". Aborting."); + return WindowManagerImpl.ADD_BAD_APP_TOKEN; + } } win = new WindowState(this, session, client, token, @@ -3962,7 +3974,6 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.willBeHidden = false; if (wtoken.hidden == visible) { - final int N = wtoken.allAppWindows.size(); boolean changed = false; if (DEBUG_APP_TRANSITIONS) Slog.v( TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden @@ -3974,23 +3985,19 @@ public class WindowManagerService extends IWindowManager.Stub if (wtoken.mAppAnimator.animation == sDummyAnimation) { wtoken.mAppAnimator.animation = null; } - applyAnimationLocked(wtoken, lp, transit, visible); - changed = true; - if (wtoken.mAppAnimator.animation != null) { + if (applyAnimationLocked(wtoken, lp, transit, visible)) { delayed = runningAppAnimation = true; } + changed = true; } + final int N = wtoken.allAppWindows.size(); for (int i=0; i<N; i++) { WindowState win = wtoken.allAppWindows.get(i); if (win == wtoken.startingWindow) { continue; } - if (win.mWinAnimator.isAnimating()) { - delayed = true; - } - //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible()); //win.dump(" "); if (visible) { @@ -4043,6 +4050,12 @@ public class WindowManagerService extends IWindowManager.Stub delayed = true; } + for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) { + if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) { + delayed = true; + } + } + return delayed; } @@ -4807,10 +4820,13 @@ public class WindowManagerService extends IWindowManager.Stub final int SW_LID = 0x00; int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LID); if (sw > 0) { - return LID_OPEN; - } else if (sw == 0) { + // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL. return LID_CLOSED; + } else if (sw == 0) { + // Switch state: AKEY_STATE_UP. + return LID_OPEN; } else { + // Switch state: AKEY_STATE_UNKNOWN. return LID_ABSENT; } } @@ -4818,10 +4834,6 @@ public class WindowManagerService extends IWindowManager.Stub // Called by window manager policy. Not exposed externally. @Override public InputChannel monitorInput(String inputChannelName) { - if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE, - "monitorInput()")) { - throw new SecurityException("Requires READ_INPUT_STATE permission"); - } return mInputManager.monitorInput(inputChannelName); } @@ -4906,7 +4918,11 @@ public class WindowManagerService extends IWindowManager.Stub // have been drawn. boolean haveBootMsg = false; boolean haveApp = false; + // if the wallpaper service is disabled on the device, we're never going to have + // wallpaper, don't bother waiting for it boolean haveWallpaper = false; + boolean wallpaperEnabled = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_enableWallpaperService); boolean haveKeyguard = true; final int N = mWindows.size(); for (int i=0; i<N; i++) { @@ -4942,7 +4958,8 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_SCREEN_ON || DEBUG_BOOT) { Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp - + " haveWall=" + haveWallpaper + " haveKeyguard=" + haveKeyguard); + + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled + + " haveKeyguard=" + haveKeyguard); } // If we are turning on the screen to show the boot message, @@ -4954,7 +4971,8 @@ public class WindowManagerService extends IWindowManager.Stub // If we are turning on the screen after the boot is completed // normally, don't do so until we have the application and // wallpaper. - if (mSystemBooted && ((!haveApp && !haveKeyguard) || !haveWallpaper)) { + if (mSystemBooted && ((!haveApp && !haveKeyguard) || + (wallpaperEnabled && !haveWallpaper))) { return; } } @@ -6871,22 +6889,33 @@ public class WindowManagerService extends IWindowManager.Stub case BULK_UPDATE_PARAMETERS: { // Used to send multiple changes from the animation side to the layout side. synchronized (mWindowMap) { + boolean doRequest = false; // TODO(cmautner): As the number of bits grows, use masks of bit groups to // eliminate unnecessary tests. if ((msg.arg1 & LayoutFields.SET_UPDATE_ROTATION) != 0) { mInnerFields.mUpdateRotation = true; + doRequest = true; } if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { mInnerFields.mWallpaperMayChange = true; + doRequest = true; } if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { mInnerFields.mWallpaperForceHidingChanged = true; + doRequest = true; } if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) { mInnerFields.mOrientationChangeComplete = false; + } else { + mInnerFields.mOrientationChangeComplete = true; + if (mWindowsFreezingScreen) { + doRequest = true; + } } - requestTraversalLocked(); + if (doRequest) { + requestTraversalLocked(); + } } break; } @@ -6897,8 +6926,6 @@ public class WindowManagerService extends IWindowManager.Stub (Pair<WindowStateAnimator, Region>) msg.obj; final WindowStateAnimator winAnimator = pair.first; winAnimator.setTransparentRegionHint(pair.second); - - scheduleAnimationLocked(); break; } @@ -7242,6 +7269,7 @@ public class WindowManagerService extends IWindowManager.Stub pw.flush(); Slog.w(TAG, "This window was lost: " + ws); Slog.w(TAG, sw.toString()); + ws.mWinAnimator.destroySurfaceLocked(); } } Slog.w(TAG, "Current app token list:"); @@ -7866,28 +7894,6 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper + " NEW: " + mWallpaperTarget + " LOWER: " + mLowerWallpaperTarget); - if (mLowerWallpaperTarget == null) { - // Whoops, we don't need a special wallpaper animation. - // Clear them out. - mAnimator.mForceHiding = false; - for (int i=mWindows.size()-1; i>=0; i--) { - WindowState w = mWindows.get(i); - if (w.mHasSurface) { - final WindowManager.LayoutParams attrs = w.mAttrs; - if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) { - if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows"); - mAnimator.mForceHiding = true; - } else if (mPolicy.canBeForceHidden(w, attrs)) { - if (!w.mWinAnimator.mAnimating) { - // We set the animation above so it - // is not yet running. - // TODO(cmautner): We lose the enter animation when this occurs. - w.mWinAnimator.clearAnimation(); - } - } - } - } - } return changes; } @@ -8001,16 +8007,18 @@ public class WindowManagerService extends IWindowManager.Stub if (!mInnerFields.mDimming) { //Slog.i(TAG, "DIM BEHIND: " + w); mInnerFields.mDimming = true; - final int width, height; - if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { - width = mCurDisplayWidth; - height = mCurDisplayHeight; - } else { - width = innerDw; - height = innerDh; + if (!mAnimator.isDimming()) { + final int width, height; + if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { + width = mCurDisplayWidth; + height = mCurDisplayHeight; + } else { + width = innerDw; + height = innerDh; + } + mAnimator.startDimming(w.mWinAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, + width, height); } - mAnimator.startDimming(w.mWinAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, - width, height); } } } @@ -8160,7 +8168,7 @@ public class WindowManagerService extends IWindowManager.Stub updateWallpaperVisibilityLocked(); } } - if (!mInnerFields.mDimming && mAnimator.mDimParams != null) { + if (!mInnerFields.mDimming && mAnimator.isDimming()) { mAnimator.stopDimming(); } } catch (RuntimeException e) { @@ -8461,11 +8469,13 @@ public class WindowManagerService extends IWindowManager.Stub !mInnerFields.mUpdateRotation) { checkDrawnWindowsLocked(); } - mInnerFields.mOrientationChangeComplete = true; // Check to see if we are now in a state where the screen should // be enabled, because the window obscured flags have changed. enableScreenIfNeededLocked(); +// Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges=" +// + Integer.toHexString(mPendingLayoutChanges) + " mLayoutNeeded=" + mLayoutNeeded +// + " animating=" + mAnimator.mAnimating); } void checkDrawnWindowsLocked() { @@ -9309,7 +9319,7 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig); pw.print(" mRotation="); pw.print(mRotation); pw.print(" mAltOrientation="); pw.println(mAltOrientation); - pw.print(" mLastWindowForcedOrientation"); pw.print(mLastWindowForcedOrientation); + pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation); pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation); pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount); if (mAnimator.mScreenRotationAnimation != null) { @@ -9501,11 +9511,6 @@ public class WindowManagerService extends IWindowManager.Stub public void onHardKeyboardStatusChange(boolean available, boolean enabled); } - void notifyAnimationChangedLayout(final int pendingLayoutChanges) { - mPendingLayoutChanges |= pendingLayoutChanges; - requestTraversalLocked(); - } - void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + @@ -9516,4 +9521,9 @@ public class WindowManagerService extends IWindowManager.Stub void bulkSetParameters(final int bulkUpdateParams) { mH.sendMessage(mH.obtainMessage(H.BULK_UPDATE_PARAMETERS, bulkUpdateParams, 0)); } + + static String getCaller() { + StackTraceElement caller = Thread.currentThread().getStackTrace()[4]; + return caller.getClassName() + "." + caller.getMethodName() + ":" + caller.getLineNumber(); + } } diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index 220f5e0..941a5e1 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -943,6 +943,10 @@ class WindowStateAnimator { } void setTransparentRegionHint(final Region region) { + if (mSurface == null) { + Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true"); + return; + } if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion"); Surface.openTransaction(); diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp index 75c20f3..85d6e11 100644 --- a/services/jni/com_android_server_input_InputManagerService.cpp +++ b/services/jni/com_android_server_input_InputManagerService.cpp @@ -39,6 +39,7 @@ #include <input/SpriteController.h> #include <android_os_MessageQueue.h> +#include <android_view_InputDevice.h> #include <android_view_KeyEvent.h> #include <android_view_MotionEvent.h> #include <android_view_InputChannel.h> @@ -88,20 +89,6 @@ static struct { } gMotionEventClassInfo; static struct { - jclass clazz; - - jmethodID ctor; - jmethodID addMotionRange; - - jfieldID mId; - jfieldID mName; - jfieldID mDescriptor; - jfieldID mSources; - jfieldID mKeyboardType; - jfieldID mKeyCharacterMapFile; -} gInputDeviceClassInfo; - -static struct { jfieldID touchscreen; jfieldID keyboard; jfieldID navigation; @@ -510,8 +497,9 @@ void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode, switch (switchCode) { case SW_LID: + // When switch value is set indicates lid is closed. env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged, - when, switchValue == 0); + when, switchValue == 0 /*lidOpen*/); checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged"); break; } @@ -1170,44 +1158,7 @@ static jobject nativeGetInputDevice(JNIEnv* env, return NULL; } - jobject deviceObj = env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor); - if (!deviceObj) { - return NULL; - } - - jstring deviceNameObj = env->NewStringUTF(deviceInfo.getName().string()); - if (!deviceNameObj) { - return NULL; - } - - jstring deviceDescriptorObj = env->NewStringUTF(deviceInfo.getDescriptor().string()); - if (!deviceDescriptorObj) { - return NULL; - } - - jstring fileStr = env->NewStringUTF(deviceInfo.getKeyCharacterMapFile()); - if (!fileStr) { - return NULL; - } - - env->SetIntField(deviceObj, gInputDeviceClassInfo.mId, deviceInfo.getId()); - env->SetObjectField(deviceObj, gInputDeviceClassInfo.mName, deviceNameObj); - env->SetObjectField(deviceObj, gInputDeviceClassInfo.mDescriptor, deviceDescriptorObj); - env->SetIntField(deviceObj, gInputDeviceClassInfo.mSources, deviceInfo.getSources()); - env->SetIntField(deviceObj, gInputDeviceClassInfo.mKeyboardType, deviceInfo.getKeyboardType()); - env->SetObjectField(deviceObj, gInputDeviceClassInfo.mKeyCharacterMapFile, fileStr); - - const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); - for (size_t i = 0; i < ranges.size(); i++) { - const InputDeviceInfo::MotionRange& range = ranges.itemAt(i); - env->CallVoidMethod(deviceObj, gInputDeviceClassInfo.addMotionRange, - range.axis, range.source, range.min, range.max, range.flat, range.fuzz); - if (env->ExceptionCheck()) { - return NULL; - } - } - - return deviceObj; + return android_view_InputDevice_create(env, deviceInfo); } static jintArray nativeGetInputDeviceIds(JNIEnv* env, @@ -1436,35 +1387,6 @@ int register_android_server_InputManager(JNIEnv* env) { FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent"); gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz)); - // InputDevice - - FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice"); - gInputDeviceClassInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceClassInfo.clazz)); - - GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz, - "<init>", "()V"); - - GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz, - "addMotionRange", "(IIFFFF)V"); - - GET_FIELD_ID(gInputDeviceClassInfo.mId, gInputDeviceClassInfo.clazz, - "mId", "I"); - - GET_FIELD_ID(gInputDeviceClassInfo.mName, gInputDeviceClassInfo.clazz, - "mName", "Ljava/lang/String;"); - - GET_FIELD_ID(gInputDeviceClassInfo.mDescriptor, gInputDeviceClassInfo.clazz, - "mDescriptor", "Ljava/lang/String;"); - - GET_FIELD_ID(gInputDeviceClassInfo.mSources, gInputDeviceClassInfo.clazz, - "mSources", "I"); - - GET_FIELD_ID(gInputDeviceClassInfo.mKeyboardType, gInputDeviceClassInfo.clazz, - "mKeyboardType", "I"); - - GET_FIELD_ID(gInputDeviceClassInfo.mKeyCharacterMapFile, gInputDeviceClassInfo.clazz, - "mKeyCharacterMapFile", "Ljava/lang/String;"); - // Configuration FIND_CLASS(clazz, "android/content/res/Configuration"); diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java index 2033db6..ba3fd3c 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -981,7 +981,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { } } - /** {@inheritDoc} */ + @Override public boolean queueIdle() { set(null); return false; diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java index 2139917..92024cd 100644 --- a/telephony/java/com/android/internal/telephony/IccCard.java +++ b/telephony/java/com/android/internal/telephony/IccCard.java @@ -580,7 +580,9 @@ public class IccCard { mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null)); } - if (oldState != State.READY && newState == State.READY) { + // Call onReady only when SIM or RUIM card becomes ready (not NV) + if (oldState != State.READY && newState == State.READY && + (is3gpp || isSubscriptionFromIccCard)) { mIccFileHandler.setAid(getAid()); mIccRecords.onReady(); } diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java index ed0081b..9f6ec71 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -205,6 +205,8 @@ public class CDMAPhone extends PhoneBase { // Sets operator numeric property by retrieving from build-time system property String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC); + log("CDMAPhone: init set 'gsm.sim.operator.numeric' to operator='" + + operatorNumeric + "'"); setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric); // Sets iso country property by retrieving from build-time system property diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java index 98a106a0..ff7a0810 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java @@ -28,6 +28,7 @@ import android.telephony.ServiceState; import android.telephony.cdma.CdmaCellLocation; import android.os.AsyncResult; import android.os.Message; +import android.os.SystemProperties; import android.provider.Telephony.Intents; import android.text.TextUtils; @@ -370,14 +371,23 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA, ss.getOperatorAlphaLong()); + String prevOperatorNumeric = + SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, ""); operatorNumeric = ss.getOperatorNumeric(); phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric); if (operatorNumeric == null) { + if (DBG) { + log("pollStateDone: operatorNumeric=" + operatorNumeric + + " prevOperatorNumeric=" + prevOperatorNumeric + + " mNeedFixZone=" + mNeedFixZone + + " clear PROPERTY_OPERATOR_ISO_COUNTRY"); + } phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, ""); mGotCountryCode = false; } else { String isoCountryCode = ""; + String mcc = operatorNumeric.substring(0, 3); try { isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(operatorNumeric .substring(0, 3))); @@ -386,11 +396,20 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { } catch (StringIndexOutOfBoundsException ex) { loge("countryCodeForMcc error" + ex); } + if (DBG) { + log("pollStateDone: operatorNumeric=" + operatorNumeric + + " prevOperatorNumeric=" + prevOperatorNumeric + + " mNeedFixZone=" + mNeedFixZone + + " mcc=" + mcc + " iso-cc=" + isoCountryCode); + } phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, isoCountryCode); mGotCountryCode = true; - if (mNeedFixZone) { + + // Fix the time zone If the operator changed or we need to fix it because + // when the NITZ time came in we didn't know the country code. + if ( ! operatorNumeric.equals(prevOperatorNumeric) || mNeedFixZone) { fixTimeZone(isoCountryCode); } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 9f27696..b694e0a 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -866,6 +866,12 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { // If the offset is (0, false) and the time zone property // is set, use the time zone property rather than GMT. String zoneName = SystemProperties.get(TIMEZONE_PROPERTY); + if (DBG) { + log("fixTimeZone zoneName='" + zoneName + + "' mZoneOffset=" + mZoneOffset + " mZoneDst=" + mZoneDst + + " iso-cc='" + isoCountryCode + + "' iso-cc-idx=" + Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode)); + } if ((mZoneOffset == 0) && (mZoneDst == false) && (zoneName != null) && (zoneName.length() > 0) && (Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode) < 0)) { @@ -880,19 +886,25 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { // Adjust the saved NITZ time to account for tzOffset. mSavedTime = mSavedTime - tzOffset; } + if (DBG) log("fixTimeZone: using default TimeZone"); } else if (isoCountryCode.equals("")) { // Country code not found. This is likely a test network. // Get a TimeZone based only on the NITZ parameters (best guess). zone = getNitzTimeZone(mZoneOffset, mZoneDst, mZoneTime); + if (DBG) log("fixTimeZone: using NITZ TimeZone"); } else { zone = TimeUtils.getTimeZone(mZoneOffset, mZoneDst, mZoneTime, isoCountryCode); + if (DBG) log("fixTimeZone: using getTimeZone(off, dst, time, iso)"); } mNeedFixZone = false; if (zone != null) { + log("fixTimeZone: zone != null zone.getID=" + zone.getID()); if (getAutoTimeZone()) { setAndBroadcastNetworkSetTimeZone(zone.getID()); + } else { + log("fixTimeZone: zone == null"); } saveNitzTimeZone(zone.getID()); } @@ -985,14 +997,23 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA, ss.getOperatorAlphaLong()); + String prevOperatorNumeric = + SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, ""); operatorNumeric = ss.getOperatorNumeric(); phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric); if (operatorNumeric == null) { + if (DBG) { + log("pollStateDone: operatorNumeric=" + operatorNumeric + + " prevOperatorNumeric=" + prevOperatorNumeric + + " mNeedFixZone=" + mNeedFixZone + + " clear PROPERTY_OPERATOR_ISO_COUNTRY"); + } phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, ""); mGotCountryCode = false; } else { String isoCountryCode = ""; + String mcc = operatorNumeric.substring(0, 3); try{ isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt( operatorNumeric.substring(0,3))); @@ -1001,11 +1022,20 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { } catch ( StringIndexOutOfBoundsException ex) { loge("pollStateDone: countryCodeForMcc error" + ex); } + if (DBG) { + log("pollStateDone: operatorNumeric=" + operatorNumeric + + " prevOperatorNumeric=" + prevOperatorNumeric + + " mNeedFixZone=" + mNeedFixZone + + " mcc=" + mcc + " iso-cc=" + isoCountryCode); + } phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, isoCountryCode); mGotCountryCode = true; - if (mNeedFixZone) { + + // Fix the time zone If the operator changed or we need to fix it because + // when the NITZ time came in we didn't know the country code. + if ( ! operatorNumeric.equals(prevOperatorNumeric) || mNeedFixZone) { fixTimeZone(isoCountryCode); } } @@ -1316,7 +1346,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { String iso = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY); if (zone == null) { - if (mGotCountryCode) { if (iso != null && iso.length() > 0) { zone = TimeUtils.getTimeZone(tzOffset, dst != 0, @@ -1332,16 +1361,21 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { } } - if (zone == null) { - // We got the time before the country, so we don't know - // how to identify the DST rules yet. Save the information - // and hope to fix it up later. + if ((zone == null) || (mZoneOffset != tzOffset) || (mZoneDst != (dst != 0))){ + // We got the time before the country or the zone has changed + // so we don't know how to identify the DST rules yet. Save + // the information and hope to fix it up later. mNeedFixZone = true; mZoneOffset = tzOffset; mZoneDst = dst != 0; mZoneTime = c.getTimeInMillis(); } + if (DBG) { + log("NITZ: tzOffset=" + tzOffset + " dst=" + dst + " zone=" + zone.getID() + + " iso=" + iso + " mGotCountryCode=" + mGotCountryCode + + " mNeedFixZone=" + mNeedFixZone); + } if (zone != null) { if (getAutoTimeZone()) { @@ -1461,6 +1495,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { * @param zoneId timezone set by carrier */ private void setAndBroadcastNetworkSetTimeZone(String zoneId) { + if (DBG) log("setAndBroadcastNetworkSetTimeZone: setTimeZone=" + zoneId); AlarmManager alarm = (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE); alarm.setTimeZone(zoneId); @@ -1477,6 +1512,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { * @param time time set by network */ private void setAndBroadcastNetworkSetTime(long time) { + if (DBG) log("setAndBroadcastNetworkSetTime: time=" + time + "ms"); SystemClock.setCurrentTimeMillis(time); Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java index 3855515..2fefa3f 100755 --- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java +++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java @@ -329,11 +329,11 @@ public final class RuimRecords extends IccRecords { @Override protected void onAllRecordsLoaded() { - log("RuimRecords: record load complete"); - // Further records that can be inserted are Operator/OEM dependent String operator = getRUIMOperatorNumeric(); + log("RuimRecords: onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" + + operator + "'"); SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator); if (mImsi != null) { diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 662f1f6..c0acf5b 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -852,12 +852,16 @@ final class GsmServiceStateTracker extends ServiceStateTracker { phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA, ss.getOperatorAlphaLong()); + String prevOperatorNumeric = + SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, ""); operatorNumeric = ss.getOperatorNumeric(); phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric); if (operatorNumeric == null) { if (DBG) { - log("pollStateDone: operatorNumeric is null:" + + log("pollStateDone: operatorNumeric=" + operatorNumeric + + " prevOperatorNumeric=" + prevOperatorNumeric + + " mNeedFixZone=" + mNeedFixZone + " clear PROPERTY_OPERATOR_ISO_COUNTRY"); } phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, ""); @@ -875,7 +879,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } if (DBG) { log("pollStateDone: operatorNumeric=" + operatorNumeric + - " mcc=" + mcc + " iso=" + iso); + " prevOperatorNumeric=" + prevOperatorNumeric + + " mNeedFixZone=" + mNeedFixZone + + " mcc=" + mcc + " iso-cc=" + iso); } phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, iso); @@ -895,7 +901,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { if ((uniqueZones.size() == 1) || testOneUniqueOffsetPath) { zone = uniqueZones.get(0); if (DBG) { - log("pollStateDone: no nitz but one TZ for iso=" + iso + + log("pollStateDone: no nitz but one TZ for iso-cc=" + iso + " with zone.getID=" + zone.getID() + " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath); } @@ -903,22 +909,24 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } else { if (DBG) { log("pollStateDone: there are " + uniqueZones.size() + - " unique offsets for iso='" + iso + + " unique offsets for iso-cc='" + iso + " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath + "', do nothing"); } } } - if (mNeedFixZone) { + // Fix the time zone If the operator changed or we need to fix it because + // when the NITZ time came in we didn't know the country code. + if ( ! operatorNumeric.equals(prevOperatorNumeric) || mNeedFixZone) { // If the offset is (0, false) and the timezone property // is set, use the timezone property rather than // GMT. String zoneName = SystemProperties.get(TIMEZONE_PROPERTY); if (DBG) { - log("pollStateDone: mNeedFixZone==true zoneName='" + zoneName + + log("pollStateDone: fix time zone zoneName='" + zoneName + "' mZoneOffset=" + mZoneOffset + " mZoneDst=" + mZoneDst + - " iso='" + iso + + " iso-cc='" + iso + "' iso-cc-idx=" + Arrays.binarySearch(GMT_COUNTRY_CODES, iso)); } if ((mZoneOffset == 0) && (mZoneDst == false) && @@ -957,15 +965,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } else { log("pollStateDone: zone == null"); } - } else { - if (DBG) { - String zoneName = SystemProperties.get(TIMEZONE_PROPERTY); - zone = TimeZone.getDefault(); - log("pollStateDone: mNeedFixZone==false zoneName='" + zoneName + - "' mZoneOffset=" + mZoneOffset + " mZoneDst=" + mZoneDst + - " iso='" + iso + - "' iso-cc-idx=" + Arrays.binarySearch(GMT_COUNTRY_CODES, iso)); - } } } @@ -1442,10 +1441,10 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } } - if (zone == null) { - // We got the time before the country, so we don't know - // how to identify the DST rules yet. Save the information - // and hope to fix it up later. + if ((zone == null) || (mZoneOffset != tzOffset) || (mZoneDst != (dst != 0))){ + // We got the time before the country or the zone has changed + // so we don't know how to identify the DST rules yet. Save + // the information and hope to fix it up later. mNeedFixZone = true; mZoneOffset = tzOffset; @@ -1556,6 +1555,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { * @param zoneId timezone set by carrier */ private void setAndBroadcastNetworkSetTimeZone(String zoneId) { + if (DBG) log("setAndBroadcastNetworkSetTimeZone: setTimeZone=" + zoneId); AlarmManager alarm = (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE); alarm.setTimeZone(zoneId); @@ -1576,6 +1576,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { * @param time time set by network */ private void setAndBroadcastNetworkSetTime(long time) { + if (DBG) log("setAndBroadcastNetworkSetTime: time=" + time + "ms"); SystemClock.setCurrentTimeMillis(time); Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java index b88af2c..80988fd 100755 --- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java +++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java @@ -228,6 +228,7 @@ public class SIMRecords extends IccRecords { adnCache.reset(); + log("SIMRecords: onRadioOffOrNotAvailable set 'gsm.sim.operator.numeric' to operator=null"); SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, null); SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, null); SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null); @@ -1254,12 +1255,12 @@ public class SIMRecords extends IccRecords { } protected void onAllRecordsLoaded() { - log("record load complete"); - String operator = getOperatorNumeric(); // Some fields require more than one SIM record to set + log("SIMRecords: onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" + + operator + "'"); SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator); if (imsi != null) { diff --git a/test-runner/src/android/test/AssertionFailedError.java b/test-runner/src/android/test/AssertionFailedError.java index 7af5806..b3ac6d1 100644 --- a/test-runner/src/android/test/AssertionFailedError.java +++ b/test-runner/src/android/test/AssertionFailedError.java @@ -19,8 +19,7 @@ package android.test; /** * Thrown when an assertion failed. * - * Note: Most users of this class should simply use junit.framework.AssertionFailedError, - * which provides the same functionality. + * @deprecated use junit.framework.AssertionFailedError */ public class AssertionFailedError extends Error { diff --git a/test-runner/src/android/test/ComparisonFailure.java b/test-runner/src/android/test/ComparisonFailure.java index e7e9698..3fa76f5 100644 --- a/test-runner/src/android/test/ComparisonFailure.java +++ b/test-runner/src/android/test/ComparisonFailure.java @@ -19,8 +19,7 @@ package android.test; /** * Thrown when an assert equals for Strings failed. * - * Note: Most users of this class should simply use junit.framework.ComparisonFailure, - * which provides the same functionality at a lighter weight. + * @deprecated use junit.framework.ComparisonFailure */ public class ComparisonFailure extends AssertionFailedError { private junit.framework.ComparisonFailure mComparison; diff --git a/test-runner/src/junit/runner/BaseTestRunner.java b/test-runner/src/junit/runner/BaseTestRunner.java index e073ef7..8cfd7fa 100644 --- a/test-runner/src/junit/runner/BaseTestRunner.java +++ b/test-runner/src/junit/runner/BaseTestRunner.java @@ -1,10 +1,24 @@ package junit.runner; -import junit.framework.*; -import java.lang.reflect.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.text.NumberFormat; -import java.io.*; -import java.util.*; +import java.util.Properties; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestListener; +import junit.framework.TestSuite; /** * Base class for all test runners. @@ -19,8 +33,8 @@ public abstract class BaseTestRunner implements TestListener { boolean fLoading= true; /* - * Implementation of TestListener - */ + * Implementation of TestListener + */ public synchronized void startTest(Test test) { testStarted(test.toString()); } @@ -32,9 +46,9 @@ public abstract class BaseTestRunner implements TestListener { protected static Properties getPreferences() { if (fPreferences == null) { fPreferences= new Properties(); - fPreferences.put("loading", "true"); - fPreferences.put("filterstack", "true"); - readPreferences(); + fPreferences.put("loading", "true"); + fPreferences.put("filterstack", "true"); + readPreferences(); } return fPreferences; } @@ -48,8 +62,9 @@ public abstract class BaseTestRunner implements TestListener { } } + // android-changed remove 'static' qualifier for API compatibility public void setPreference(String key, String value) { - getPreferences().setProperty(key, value); + getPreferences().put(key, value); } public synchronized void endTest(Test test) { @@ -97,8 +112,8 @@ public abstract class BaseTestRunner implements TestListener { Method suiteMethod= null; try { suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]); - } catch(Exception e) { - // try to extract a test suite automatically + } catch(Exception e) { + // try to extract a test suite automatically clearStatus(); return new TestSuite(testClass); } @@ -108,7 +123,7 @@ public abstract class BaseTestRunner implements TestListener { } Test test= null; try { - test= (Test)suiteMethod.invoke(null); // static method + test= (Test)suiteMethod.invoke(null, (Object[])new Class[0]); // static method if (test == null) return test; } @@ -163,7 +178,7 @@ public abstract class BaseTestRunner implements TestListener { fLoading= enable; } /** - * Extract the class name from a String + * Extract the class name from a String in VA/Java style */ public String extractClassName(String className) { if(className.startsWith("Default package for")) @@ -186,42 +201,46 @@ public abstract class BaseTestRunner implements TestListener { */ protected abstract void runFailed(String message); + // BEGIN android-changed - add back getLoader() for API compatibility /** - * Returns the loaded Class for a suite name. + * Returns the loader to be used. + * + * @deprecated not present in JUnit4.10 */ - protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException { - return getLoader().load(suiteClassName); + public TestSuiteLoader getLoader() { + if (useReloadingTestSuiteLoader()) + return new ReloadingTestSuiteLoader(); + return new StandardTestSuiteLoader(); } + // END android-changed /** - * Clears the status message. + * Returns the loaded Class for a suite name. */ - protected void clearStatus() { // Belongs in the GUI TestRunner class + protected Class<?> loadSuiteClass(String suiteClassName) throws ClassNotFoundException { + return Class.forName(suiteClassName); } /** - * Returns the loader to be used. + * Clears the status message. */ - public TestSuiteLoader getLoader() { - if (useReloadingTestSuiteLoader()) - return new ReloadingTestSuiteLoader(); - return new StandardTestSuiteLoader(); + protected void clearStatus() { // Belongs in the GUI TestRunner class } protected boolean useReloadingTestSuiteLoader() { - return getPreference("loading").equals("true") && !inVAJava() && fLoading; + return getPreference("loading").equals("true") && fLoading; } private static File getPreferencesFile() { - String home= System.getProperty("user.home"); - return new File(home, "junit.properties"); - } - - private static void readPreferences() { - InputStream is= null; - try { - is= new FileInputStream(getPreferencesFile()); - setPreferences(new Properties(getPreferences())); + String home= System.getProperty("user.home"); + return new File(home, "junit.properties"); + } + + private static void readPreferences() { + InputStream is= null; + try { + is= new FileInputStream(getPreferencesFile()); + setPreferences(new Properties(getPreferences())); getPreferences().load(is); } catch (IOException e) { try { @@ -230,32 +249,22 @@ public abstract class BaseTestRunner implements TestListener { } catch (IOException e1) { } } - } - - public static String getPreference(String key) { - return getPreferences().getProperty(key); - } - - public static int getPreference(String key, int dflt) { - String value= getPreference(key); - int intValue= dflt; - if (value == null) - return intValue; - try { - intValue= Integer.parseInt(value); - } catch (NumberFormatException ne) { - } - return intValue; - } - - public static boolean inVAJava() { + } + + public static String getPreference(String key) { + return getPreferences().getProperty(key); + } + + public static int getPreference(String key, int dflt) { + String value= getPreference(key); + int intValue= dflt; + if (value == null) + return intValue; try { - Class.forName("com.ibm.uvm.tools.DebugSupport"); + intValue= Integer.parseInt(value); + } catch (NumberFormatException ne) { } - catch (Exception e) { - return false; - } - return true; + return intValue; } /** @@ -270,6 +279,13 @@ public abstract class BaseTestRunner implements TestListener { return BaseTestRunner.getFilteredTrace(trace); } + // BEGIN android-changed - add back this method for API compatibility + /** @deprecated not present in JUnit4.10 */ + public static boolean inVAJava() { + return false; + } + // END android-changed + /** * Filters stack frames from internal JUnit classes */ @@ -303,14 +319,14 @@ public abstract class BaseTestRunner implements TestListener { static boolean filterLine(String line) { String[] patterns= new String[] { - "junit.framework.TestCase", - "junit.framework.TestResult", - "junit.framework.TestSuite", - "junit.framework.Assert.", // don't filter AssertionFailure - "junit.swingui.TestRunner", - "junit.awtui.TestRunner", - "junit.textui.TestRunner", - "java.lang.reflect.Method.invoke(" + "junit.framework.TestCase", + "junit.framework.TestResult", + "junit.framework.TestSuite", + "junit.framework.Assert.", // don't filter AssertionFailure + "junit.swingui.TestRunner", + "junit.awtui.TestRunner", + "junit.textui.TestRunner", + "java.lang.reflect.Method.invoke(" }; for (int i= 0; i < patterns.length; i++) { if (line.indexOf(patterns[i]) > 0) @@ -319,8 +335,8 @@ public abstract class BaseTestRunner implements TestListener { return false; } - static { - fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength); - } + static { + fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength); + } } diff --git a/test-runner/src/junit/runner/ClassPathTestCollector.java b/test-runner/src/junit/runner/ClassPathTestCollector.java index 8a3c702..f48ddee 100644 --- a/test-runner/src/junit/runner/ClassPathTestCollector.java +++ b/test-runner/src/junit/runner/ClassPathTestCollector.java @@ -13,69 +13,69 @@ import java.io.*; * {@hide} - Not needed for 1.0 SDK */ public abstract class ClassPathTestCollector implements TestCollector { - - static final int SUFFIX_LENGTH= ".class".length(); - - public ClassPathTestCollector() { - } - - public Enumeration collectTests() { - String classPath= System.getProperty("java.class.path"); - Hashtable result = collectFilesInPath(classPath); - return result.elements(); - } - public Hashtable collectFilesInPath(String classPath) { - Hashtable result= collectFilesInRoots(splitClassPath(classPath)); - return result; - } - - Hashtable collectFilesInRoots(Vector roots) { - Hashtable result= new Hashtable(100); - Enumeration e= roots.elements(); - while (e.hasMoreElements()) - gatherFiles(new File((String)e.nextElement()), "", result); - return result; - } + static final int SUFFIX_LENGTH= ".class".length(); - void gatherFiles(File classRoot, String classFileName, Hashtable result) { - File thisRoot= new File(classRoot, classFileName); - if (thisRoot.isFile()) { - if (isTestClass(classFileName)) { - String className= classNameFromFile(classFileName); - result.put(className, className); - } - return; - } - String[] contents= thisRoot.list(); - if (contents != null) { - for (int i= 0; i < contents.length; i++) - gatherFiles(classRoot, classFileName+File.separatorChar+contents[i], result); - } - } - - Vector splitClassPath(String classPath) { - Vector result= new Vector(); - String separator= System.getProperty("path.separator"); - StringTokenizer tokenizer= new StringTokenizer(classPath, separator); - while (tokenizer.hasMoreTokens()) - result.addElement(tokenizer.nextToken()); - return result; - } - - protected boolean isTestClass(String classFileName) { - return - classFileName.endsWith(".class") && - classFileName.indexOf('$') < 0 && - classFileName.indexOf("Test") > 0; - } - - protected String classNameFromFile(String classFileName) { - // convert /a/b.class to a.b - String s= classFileName.substring(0, classFileName.length()-SUFFIX_LENGTH); - String s2= s.replace(File.separatorChar, '.'); - if (s2.startsWith(".")) - return s2.substring(1); - return s2; - } + public ClassPathTestCollector() { + } + + public Enumeration collectTests() { + String classPath= System.getProperty("java.class.path"); + Hashtable result = collectFilesInPath(classPath); + return result.elements(); + } + + public Hashtable collectFilesInPath(String classPath) { + Hashtable result= collectFilesInRoots(splitClassPath(classPath)); + return result; + } + + Hashtable collectFilesInRoots(Vector roots) { + Hashtable result= new Hashtable(100); + Enumeration e= roots.elements(); + while (e.hasMoreElements()) + gatherFiles(new File((String)e.nextElement()), "", result); + return result; + } + + void gatherFiles(File classRoot, String classFileName, Hashtable result) { + File thisRoot= new File(classRoot, classFileName); + if (thisRoot.isFile()) { + if (isTestClass(classFileName)) { + String className= classNameFromFile(classFileName); + result.put(className, className); + } + return; + } + String[] contents= thisRoot.list(); + if (contents != null) { + for (int i= 0; i < contents.length; i++) + gatherFiles(classRoot, classFileName+File.separatorChar+contents[i], result); + } + } + + Vector splitClassPath(String classPath) { + Vector result= new Vector(); + String separator= System.getProperty("path.separator"); + StringTokenizer tokenizer= new StringTokenizer(classPath, separator); + while (tokenizer.hasMoreTokens()) + result.addElement(tokenizer.nextToken()); + return result; + } + + protected boolean isTestClass(String classFileName) { + return + classFileName.endsWith(".class") && + classFileName.indexOf('$') < 0 && + classFileName.indexOf("Test") > 0; + } + + protected String classNameFromFile(String classFileName) { + // convert /a/b.class to a.b + String s= classFileName.substring(0, classFileName.length()-SUFFIX_LENGTH); + String s2= s.replace(File.separatorChar, '.'); + if (s2.startsWith(".")) + return s2.substring(1); + return s2; + } } diff --git a/test-runner/src/junit/runner/FailureDetailView.java b/test-runner/src/junit/runner/FailureDetailView.java index 7108cec..1b8365a 100644 --- a/test-runner/src/junit/runner/FailureDetailView.java +++ b/test-runner/src/junit/runner/FailureDetailView.java @@ -1,7 +1,7 @@ package junit.runner; // The following line was removed for compatibility with Android libraries. -//import java.awt.Component; +//import java.awt.Component; import junit.framework.*; @@ -17,12 +17,12 @@ public interface FailureDetailView { // */ // public Component getComponent(); - /** - * Shows details of a TestFailure - */ - public void showFailure(TestFailure failure); - /** - * Clears the view - */ - public void clear(); + /** + * Shows details of a TestFailure + */ + public void showFailure(TestFailure failure); + /** + * Clears the view + */ + public void clear(); } diff --git a/test-runner/src/junit/runner/LoadingTestCollector.java b/test-runner/src/junit/runner/LoadingTestCollector.java index b1760b1..489d9d6 100644 --- a/test-runner/src/junit/runner/LoadingTestCollector.java +++ b/test-runner/src/junit/runner/LoadingTestCollector.java @@ -12,59 +12,59 @@ import junit.framework.*; * {@hide} - Not needed for 1.0 SDK */ public class LoadingTestCollector extends ClassPathTestCollector { - - TestCaseClassLoader fLoader; - - public LoadingTestCollector() { - fLoader= new TestCaseClassLoader(); - } - - protected boolean isTestClass(String classFileName) { - try { - if (classFileName.endsWith(".class")) { - Class testClass= classFromFile(classFileName); - return (testClass != null) && isTestClass(testClass); - } - } - catch (ClassNotFoundException expected) { - } - catch (NoClassDefFoundError notFatal) { - } - return false; - } - - Class classFromFile(String classFileName) throws ClassNotFoundException { - String className= classNameFromFile(classFileName); - if (!fLoader.isExcluded(className)) - return fLoader.loadClass(className, false); - return null; - } - - boolean isTestClass(Class testClass) { - if (hasSuiteMethod(testClass)) - return true; - if (Test.class.isAssignableFrom(testClass) && - Modifier.isPublic(testClass.getModifiers()) && - hasPublicConstructor(testClass)) - return true; - return false; - } - - boolean hasSuiteMethod(Class testClass) { - try { - testClass.getMethod(BaseTestRunner.SUITE_METHODNAME, new Class[0]); - } catch(Exception e) { - return false; - } - return true; - } - - boolean hasPublicConstructor(Class testClass) { - try { - TestSuite.getTestConstructor(testClass); - } catch(NoSuchMethodException e) { - return false; - } - return true; - } + + TestCaseClassLoader fLoader; + + public LoadingTestCollector() { + fLoader= new TestCaseClassLoader(); + } + + protected boolean isTestClass(String classFileName) { + try { + if (classFileName.endsWith(".class")) { + Class testClass= classFromFile(classFileName); + return (testClass != null) && isTestClass(testClass); + } + } + catch (ClassNotFoundException expected) { + } + catch (NoClassDefFoundError notFatal) { + } + return false; + } + + Class classFromFile(String classFileName) throws ClassNotFoundException { + String className= classNameFromFile(classFileName); + if (!fLoader.isExcluded(className)) + return fLoader.loadClass(className, false); + return null; + } + + boolean isTestClass(Class testClass) { + if (hasSuiteMethod(testClass)) + return true; + if (Test.class.isAssignableFrom(testClass) && + Modifier.isPublic(testClass.getModifiers()) && + hasPublicConstructor(testClass)) + return true; + return false; + } + + boolean hasSuiteMethod(Class testClass) { + try { + testClass.getMethod(BaseTestRunner.SUITE_METHODNAME, new Class[0]); + } catch(Exception e) { + return false; + } + return true; + } + + boolean hasPublicConstructor(Class testClass) { + try { + TestSuite.getTestConstructor(testClass); + } catch(NoSuchMethodException e) { + return false; + } + return true; + } } diff --git a/test-runner/src/junit/runner/ReloadingTestSuiteLoader.java b/test-runner/src/junit/runner/ReloadingTestSuiteLoader.java index a6d84fe..c4d80d0 100644 --- a/test-runner/src/junit/runner/ReloadingTestSuiteLoader.java +++ b/test-runner/src/junit/runner/ReloadingTestSuiteLoader.java @@ -5,16 +5,16 @@ package junit.runner; * {@hide} - Not needed for 1.0 SDK */ public class ReloadingTestSuiteLoader implements TestSuiteLoader { - - public Class load(String suiteClassName) throws ClassNotFoundException { - return createLoader().loadClass(suiteClassName, true); - } - - public Class reload(Class aClass) throws ClassNotFoundException { - return createLoader().loadClass(aClass.getName(), true); - } - - protected TestCaseClassLoader createLoader() { - return new TestCaseClassLoader(); - } + + public Class load(String suiteClassName) throws ClassNotFoundException { + return createLoader().loadClass(suiteClassName, true); + } + + public Class reload(Class aClass) throws ClassNotFoundException { + return createLoader().loadClass(aClass.getName(), true); + } + + protected TestCaseClassLoader createLoader() { + return new TestCaseClassLoader(); + } } diff --git a/test-runner/src/junit/runner/SimpleTestCollector.java b/test-runner/src/junit/runner/SimpleTestCollector.java index 543168f..6cb0e19 100644 --- a/test-runner/src/junit/runner/SimpleTestCollector.java +++ b/test-runner/src/junit/runner/SimpleTestCollector.java @@ -8,14 +8,14 @@ package junit.runner; * {@hide} - Not needed for 1.0 SDK */ public class SimpleTestCollector extends ClassPathTestCollector { - - public SimpleTestCollector() { - } - - protected boolean isTestClass(String classFileName) { - return - classFileName.endsWith(".class") && - classFileName.indexOf('$') < 0 && - classFileName.indexOf("Test") > 0; - } + + public SimpleTestCollector() { + } + + protected boolean isTestClass(String classFileName) { + return + classFileName.endsWith(".class") && + classFileName.indexOf('$') < 0 && + classFileName.indexOf("Test") > 0; + } } diff --git a/test-runner/src/junit/runner/Sorter.java b/test-runner/src/junit/runner/Sorter.java index 66f551e..7731f66 100644 --- a/test-runner/src/junit/runner/Sorter.java +++ b/test-runner/src/junit/runner/Sorter.java @@ -11,29 +11,29 @@ import junit.runner.*; * {@hide} - Not needed for 1.0 SDK */ public class Sorter { - public static interface Swapper { - public void swap(Vector values, int left, int right); - } - - public static void sortStrings(Vector values , int left, int right, Swapper swapper) { - int oleft= left; - int oright= right; - String mid= (String)values.elementAt((left + right) / 2); - do { - while (((String)(values.elementAt(left))).compareTo(mid) < 0) - left++; - while (mid.compareTo((String)(values.elementAt(right))) < 0) - right--; - if (left <= right) { - swapper.swap(values, left, right); - left++; - right--; - } - } while (left <= right); - - if (oleft < right) - sortStrings(values, oleft, right, swapper); - if (left < oright) - sortStrings(values, left, oright, swapper); - } + public static interface Swapper { + public void swap(Vector values, int left, int right); + } + + public static void sortStrings(Vector values , int left, int right, Swapper swapper) { + int oleft= left; + int oright= right; + String mid= (String)values.elementAt((left + right) / 2); + do { + while (((String)(values.elementAt(left))).compareTo(mid) < 0) + left++; + while (mid.compareTo((String)(values.elementAt(right))) < 0) + right--; + if (left <= right) { + swapper.swap(values, left, right); + left++; + right--; + } + } while (left <= right); + + if (oleft < right) + sortStrings(values, oleft, right, swapper); + if (left < oright) + sortStrings(values, left, oright, swapper); + } } diff --git a/test-runner/src/junit/runner/StandardTestSuiteLoader.java b/test-runner/src/junit/runner/StandardTestSuiteLoader.java index bce7dec..381e684 100644 --- a/test-runner/src/junit/runner/StandardTestSuiteLoader.java +++ b/test-runner/src/junit/runner/StandardTestSuiteLoader.java @@ -5,16 +5,16 @@ package junit.runner; * {@hide} - Not needed for 1.0 SDK */ public class StandardTestSuiteLoader implements TestSuiteLoader { - /** - * Uses the system class loader to load the test class - */ - public Class load(String suiteClassName) throws ClassNotFoundException { - return Class.forName(suiteClassName); - } - /** - * Uses the system class loader to load the test class - */ - public Class reload(Class aClass) throws ClassNotFoundException { - return aClass; - } + /** + * Uses the system class loader to load the test class + */ + public Class load(String suiteClassName) throws ClassNotFoundException { + return Class.forName(suiteClassName); + } + /** + * Uses the system class loader to load the test class + */ + public Class reload(Class aClass) throws ClassNotFoundException { + return aClass; + } } diff --git a/test-runner/src/junit/runner/TestCaseClassLoader.java b/test-runner/src/junit/runner/TestCaseClassLoader.java index 3a510c6..09eec7f 100644 --- a/test-runner/src/junit/runner/TestCaseClassLoader.java +++ b/test-runner/src/junit/runner/TestCaseClassLoader.java @@ -14,7 +14,7 @@ import java.util.zip.*; * loader. They will be shared across test runs. * <p> * The list of excluded package paths is specified in - * a properties file "excluded.properties" that is located in + * a properties file "excluded.properties" that is located in * the same place as the TestCaseClassLoader class. * <p> * <b>Known limitation:</b> the TestCaseClassLoader cannot load classes @@ -22,204 +22,204 @@ import java.util.zip.*; * {@hide} - Not needed for 1.0 SDK */ public class TestCaseClassLoader extends ClassLoader { - /** scanned class path */ - private Vector fPathItems; - /** default excluded paths */ - private String[] defaultExclusions= { - "junit.framework.", - "junit.extensions.", - "junit.runner." - }; - /** name of excluded properties file */ - static final String EXCLUDED_FILE= "excluded.properties"; - /** excluded paths */ - private Vector fExcluded; - - /** - * Constructs a TestCaseLoader. It scans the class path - * and the excluded package paths - */ - public TestCaseClassLoader() { - this(System.getProperty("java.class.path")); - } - - /** - * Constructs a TestCaseLoader. It scans the class path - * and the excluded package paths - */ - public TestCaseClassLoader(String classPath) { - scanPath(classPath); - readExcludedPackages(); - } - - private void scanPath(String classPath) { - String separator= System.getProperty("path.separator"); - fPathItems= new Vector(10); - StringTokenizer st= new StringTokenizer(classPath, separator); - while (st.hasMoreTokens()) { - fPathItems.addElement(st.nextToken()); - } - } - - public URL getResource(String name) { - return ClassLoader.getSystemResource(name); - } - - public InputStream getResourceAsStream(String name) { - return ClassLoader.getSystemResourceAsStream(name); - } - - public boolean isExcluded(String name) { - for (int i= 0; i < fExcluded.size(); i++) { - if (name.startsWith((String) fExcluded.elementAt(i))) { - return true; - } - } - return false; - } - - public synchronized Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - - Class c= findLoadedClass(name); - if (c != null) - return c; - // - // Delegate the loading of excluded classes to the - // standard class loader. - // - if (isExcluded(name)) { - try { - c= findSystemClass(name); - return c; - } catch (ClassNotFoundException e) { - // keep searching - } - } - if (c == null) { - byte[] data= lookupClassData(name); - if (data == null) - throw new ClassNotFoundException(); - c= defineClass(name, data, 0, data.length); - } - if (resolve) - resolveClass(c); - return c; - } - - private byte[] lookupClassData(String className) throws ClassNotFoundException { - byte[] data= null; - for (int i= 0; i < fPathItems.size(); i++) { - String path= (String) fPathItems.elementAt(i); - String fileName= className.replace('.', '/')+".class"; - if (isJar(path)) { - data= loadJarData(path, fileName); - } else { - data= loadFileData(path, fileName); - } - if (data != null) - return data; - } - throw new ClassNotFoundException(className); - } - - boolean isJar(String pathEntry) { - return pathEntry.endsWith(".jar") || - pathEntry.endsWith(".apk") || - pathEntry.endsWith(".zip"); - } - - private byte[] loadFileData(String path, String fileName) { - File file= new File(path, fileName); - if (file.exists()) { - return getClassData(file); - } - return null; - } - - private byte[] getClassData(File f) { - try { - FileInputStream stream= new FileInputStream(f); - ByteArrayOutputStream out= new ByteArrayOutputStream(1000); - byte[] b= new byte[1000]; - int n; - while ((n= stream.read(b)) != -1) - out.write(b, 0, n); - stream.close(); - out.close(); - return out.toByteArray(); - - } catch (IOException e) { - } - return null; - } - - private byte[] loadJarData(String path, String fileName) { - ZipFile zipFile= null; - InputStream stream= null; - File archive= new File(path); - if (!archive.exists()) - return null; - try { - zipFile= new ZipFile(archive); - } catch(IOException io) { - return null; - } - ZipEntry entry= zipFile.getEntry(fileName); - if (entry == null) - return null; - int size= (int) entry.getSize(); - try { - stream= zipFile.getInputStream(entry); - byte[] data= new byte[size]; - int pos= 0; - while (pos < size) { - int n= stream.read(data, pos, data.length - pos); - pos += n; - } - zipFile.close(); - return data; - } catch (IOException e) { - } finally { - try { - if (stream != null) - stream.close(); - } catch (IOException e) { - } - } - return null; - } - - private void readExcludedPackages() { - fExcluded= new Vector(10); - for (int i= 0; i < defaultExclusions.length; i++) - fExcluded.addElement(defaultExclusions[i]); - - InputStream is= getClass().getResourceAsStream(EXCLUDED_FILE); - if (is == null) - return; - Properties p= new Properties(); - try { - p.load(is); - } - catch (IOException e) { - return; - } finally { - try { - is.close(); - } catch (IOException e) { - } - } - for (Enumeration e= p.propertyNames(); e.hasMoreElements(); ) { - String key= (String)e.nextElement(); - if (key.startsWith("excluded.")) { - String path= p.getProperty(key); - path= path.trim(); - if (path.endsWith("*")) - path= path.substring(0, path.length()-1); - if (path.length() > 0) - fExcluded.addElement(path); - } - } - } + /** scanned class path */ + private Vector fPathItems; + /** default excluded paths */ + private String[] defaultExclusions= { + "junit.framework.", + "junit.extensions.", + "junit.runner." + }; + /** name of excluded properties file */ + static final String EXCLUDED_FILE= "excluded.properties"; + /** excluded paths */ + private Vector fExcluded; + + /** + * Constructs a TestCaseLoader. It scans the class path + * and the excluded package paths + */ + public TestCaseClassLoader() { + this(System.getProperty("java.class.path")); + } + + /** + * Constructs a TestCaseLoader. It scans the class path + * and the excluded package paths + */ + public TestCaseClassLoader(String classPath) { + scanPath(classPath); + readExcludedPackages(); + } + + private void scanPath(String classPath) { + String separator= System.getProperty("path.separator"); + fPathItems= new Vector(10); + StringTokenizer st= new StringTokenizer(classPath, separator); + while (st.hasMoreTokens()) { + fPathItems.addElement(st.nextToken()); + } + } + + public URL getResource(String name) { + return ClassLoader.getSystemResource(name); + } + + public InputStream getResourceAsStream(String name) { + return ClassLoader.getSystemResourceAsStream(name); + } + + public boolean isExcluded(String name) { + for (int i= 0; i < fExcluded.size(); i++) { + if (name.startsWith((String) fExcluded.elementAt(i))) { + return true; + } + } + return false; + } + + public synchronized Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + + Class c= findLoadedClass(name); + if (c != null) + return c; + // + // Delegate the loading of excluded classes to the + // standard class loader. + // + if (isExcluded(name)) { + try { + c= findSystemClass(name); + return c; + } catch (ClassNotFoundException e) { + // keep searching + } + } + if (c == null) { + byte[] data= lookupClassData(name); + if (data == null) + throw new ClassNotFoundException(); + c= defineClass(name, data, 0, data.length); + } + if (resolve) + resolveClass(c); + return c; + } + + private byte[] lookupClassData(String className) throws ClassNotFoundException { + byte[] data= null; + for (int i= 0; i < fPathItems.size(); i++) { + String path= (String) fPathItems.elementAt(i); + String fileName= className.replace('.', '/')+".class"; + if (isJar(path)) { + data= loadJarData(path, fileName); + } else { + data= loadFileData(path, fileName); + } + if (data != null) + return data; + } + throw new ClassNotFoundException(className); + } + + boolean isJar(String pathEntry) { + return pathEntry.endsWith(".jar") || + pathEntry.endsWith(".apk") || + pathEntry.endsWith(".zip"); + } + + private byte[] loadFileData(String path, String fileName) { + File file= new File(path, fileName); + if (file.exists()) { + return getClassData(file); + } + return null; + } + + private byte[] getClassData(File f) { + try { + FileInputStream stream= new FileInputStream(f); + ByteArrayOutputStream out= new ByteArrayOutputStream(1000); + byte[] b= new byte[1000]; + int n; + while ((n= stream.read(b)) != -1) + out.write(b, 0, n); + stream.close(); + out.close(); + return out.toByteArray(); + + } catch (IOException e) { + } + return null; + } + + private byte[] loadJarData(String path, String fileName) { + ZipFile zipFile= null; + InputStream stream= null; + File archive= new File(path); + if (!archive.exists()) + return null; + try { + zipFile= new ZipFile(archive); + } catch(IOException io) { + return null; + } + ZipEntry entry= zipFile.getEntry(fileName); + if (entry == null) + return null; + int size= (int) entry.getSize(); + try { + stream= zipFile.getInputStream(entry); + byte[] data= new byte[size]; + int pos= 0; + while (pos < size) { + int n= stream.read(data, pos, data.length - pos); + pos += n; + } + zipFile.close(); + return data; + } catch (IOException e) { + } finally { + try { + if (stream != null) + stream.close(); + } catch (IOException e) { + } + } + return null; + } + + private void readExcludedPackages() { + fExcluded= new Vector(10); + for (int i= 0; i < defaultExclusions.length; i++) + fExcluded.addElement(defaultExclusions[i]); + + InputStream is= getClass().getResourceAsStream(EXCLUDED_FILE); + if (is == null) + return; + Properties p= new Properties(); + try { + p.load(is); + } + catch (IOException e) { + return; + } finally { + try { + is.close(); + } catch (IOException e) { + } + } + for (Enumeration e= p.propertyNames(); e.hasMoreElements(); ) { + String key= (String)e.nextElement(); + if (key.startsWith("excluded.")) { + String path= p.getProperty(key); + path= path.trim(); + if (path.endsWith("*")) + path= path.substring(0, path.length()-1); + if (path.length() > 0) + fExcluded.addElement(path); + } + } + } } diff --git a/test-runner/src/junit/runner/TestCollector.java b/test-runner/src/junit/runner/TestCollector.java index 208dccd..3ac9d9e 100644 --- a/test-runner/src/junit/runner/TestCollector.java +++ b/test-runner/src/junit/runner/TestCollector.java @@ -5,13 +5,13 @@ import java.util.*; /** * Collects Test class names to be presented - * by the TestSelector. + * by the TestSelector. * @see TestSelector * {@hide} - Not needed for 1.0 SDK */ public interface TestCollector { - /** - * Returns an enumeration of Strings with qualified class names - */ - public Enumeration collectTests(); + /** + * Returns an enumeration of Strings with qualified class names + */ + public Enumeration collectTests(); } diff --git a/test-runner/src/junit/runner/TestRunListener.java b/test-runner/src/junit/runner/TestRunListener.java index 0e95819..0410f0c 100644 --- a/test-runner/src/junit/runner/TestRunListener.java +++ b/test-runner/src/junit/runner/TestRunListener.java @@ -6,15 +6,15 @@ package junit.runner; * making it suitable for remote test execution. * {@hide} - Not needed for 1.0 SDK */ - public interface TestRunListener { - /* test status constants*/ - public static final int STATUS_ERROR= 1; - public static final int STATUS_FAILURE= 2; +public interface TestRunListener { + /* test status constants*/ + public static final int STATUS_ERROR= 1; + public static final int STATUS_FAILURE= 2; - public void testRunStarted(String testSuiteName, int testCount); - public void testRunEnded(long elapsedTime); - public void testRunStopped(long elapsedTime); - public void testStarted(String testName); - public void testEnded(String testName); - public void testFailed(int status, String testName, String trace); + public void testRunStarted(String testSuiteName, int testCount); + public void testRunEnded(long elapsedTime); + public void testRunStopped(long elapsedTime); + public void testStarted(String testName); + public void testEnded(String testName); + public void testFailed(int status, String testName, String trace); } diff --git a/test-runner/src/junit/runner/TestSuiteLoader.java b/test-runner/src/junit/runner/TestSuiteLoader.java index 39a4cf7..581ea23 100644 --- a/test-runner/src/junit/runner/TestSuiteLoader.java +++ b/test-runner/src/junit/runner/TestSuiteLoader.java @@ -4,6 +4,6 @@ package junit.runner; * An interface to define how a test suite should be loaded. */ public interface TestSuiteLoader { - abstract public Class load(String suiteClassName) throws ClassNotFoundException; - abstract public Class reload(Class aClass) throws ClassNotFoundException; + abstract public Class load(String suiteClassName) throws ClassNotFoundException; + abstract public Class reload(Class aClass) throws ClassNotFoundException; } diff --git a/test-runner/src/junit/runner/Version.java b/test-runner/src/junit/runner/Version.java index b4541ab..4a6dc85 100644 --- a/test-runner/src/junit/runner/Version.java +++ b/test-runner/src/junit/runner/Version.java @@ -4,11 +4,17 @@ package junit.runner; * This class defines the current version of JUnit */ public class Version { - private Version() { - // don't instantiate - } + private Version() { + // don't instantiate + } - public static String id() { - return "3.8.1"; - } + public static String id() { + return "4.10"; + } + + // android-changed + /** @hide - not needed for public API */ + public static void main(String[] args) { + System.out.println(id()); + } } diff --git a/test-runner/src/junit/textui/ResultPrinter.java b/test-runner/src/junit/textui/ResultPrinter.java index 5c97112..4b26558 100644 --- a/test-runner/src/junit/textui/ResultPrinter.java +++ b/test-runner/src/junit/textui/ResultPrinter.java @@ -14,129 +14,129 @@ import junit.framework.TestResult; import junit.runner.BaseTestRunner; public class ResultPrinter implements TestListener { - PrintStream fWriter; - int fColumn= 0; - - public ResultPrinter(PrintStream writer) { - fWriter= writer; - } - - /* API for use by textui.TestRunner - */ - - synchronized void print(TestResult result, long runTime) { - printHeader(runTime); - printErrors(result); - printFailures(result); - printFooter(result); - } - - void printWaitPrompt() { - getWriter().println(); - getWriter().println("<RETURN> to continue"); - } - - /* Internal methods - */ - - protected void printHeader(long runTime) { - getWriter().println(); - getWriter().println("Time: "+elapsedTimeAsString(runTime)); - } - - protected void printErrors(TestResult result) { - printDefects(result.errors(), result.errorCount(), "error"); - } - - protected void printFailures(TestResult result) { - printDefects(result.failures(), result.failureCount(), "failure"); - } - - protected void printDefects(Enumeration booBoos, int count, String type) { - if (count == 0) return; - if (count == 1) - getWriter().println("There was " + count + " " + type + ":"); - else - getWriter().println("There were " + count + " " + type + "s:"); - for (int i= 1; booBoos.hasMoreElements(); i++) { - printDefect((TestFailure) booBoos.nextElement(), i); - } - } - - public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes - printDefectHeader(booBoo, count); - printDefectTrace(booBoo); - } - - protected void printDefectHeader(TestFailure booBoo, int count) { - // I feel like making this a println, then adding a line giving the throwable a chance to print something - // before we get to the stack trace. - getWriter().print(count + ") " + booBoo.failedTest()); - } - - protected void printDefectTrace(TestFailure booBoo) { - getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace())); - } - - protected void printFooter(TestResult result) { - if (result.wasSuccessful()) { - getWriter().println(); - getWriter().print("OK"); - getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")"); - - } else { - getWriter().println(); - getWriter().println("FAILURES!!!"); - getWriter().println("Tests run: "+result.runCount()+ - ", Failures: "+result.failureCount()+ - ", Errors: "+result.errorCount()); - } - getWriter().println(); - } - - - /** - * Returns the formatted string of the elapsed time. - * Duplicated from BaseTestRunner. Fix it. - */ - protected String elapsedTimeAsString(long runTime) { - // The following line was altered for compatibility with - // Android libraries. - return Double.toString((double)runTime/1000); - } - - public PrintStream getWriter() { - return fWriter; - } - /** - * @see junit.framework.TestListener#addError(Test, Throwable) - */ - public void addError(Test test, Throwable t) { - getWriter().print("E"); - } - - /** - * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError) - */ - public void addFailure(Test test, AssertionFailedError t) { - getWriter().print("F"); - } - - /** - * @see junit.framework.TestListener#endTest(Test) - */ - public void endTest(Test test) { - } - - /** - * @see junit.framework.TestListener#startTest(Test) - */ - public void startTest(Test test) { - getWriter().print("."); - if (fColumn++ >= 40) { - getWriter().println(); - fColumn= 0; - } - } + PrintStream fWriter; + int fColumn= 0; + + public ResultPrinter(PrintStream writer) { + fWriter= writer; + } + + /* API for use by textui.TestRunner + */ + + synchronized void print(TestResult result, long runTime) { + printHeader(runTime); + printErrors(result); + printFailures(result); + printFooter(result); + } + + void printWaitPrompt() { + getWriter().println(); + getWriter().println("<RETURN> to continue"); + } + + /* Internal methods + */ + + protected void printHeader(long runTime) { + getWriter().println(); + getWriter().println("Time: "+elapsedTimeAsString(runTime)); + } + + protected void printErrors(TestResult result) { + printDefects(result.errors(), result.errorCount(), "error"); + } + + protected void printFailures(TestResult result) { + printDefects(result.failures(), result.failureCount(), "failure"); + } + + protected void printDefects(Enumeration<TestFailure> booBoos, int count, String type) { + if (count == 0) return; + if (count == 1) + getWriter().println("There was " + count + " " + type + ":"); + else + getWriter().println("There were " + count + " " + type + "s:"); + for (int i= 1; booBoos.hasMoreElements(); i++) { + printDefect(booBoos.nextElement(), i); + } + } + + public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes + printDefectHeader(booBoo, count); + printDefectTrace(booBoo); + } + + protected void printDefectHeader(TestFailure booBoo, int count) { + // I feel like making this a println, then adding a line giving the throwable a chance to print something + // before we get to the stack trace. + getWriter().print(count + ") " + booBoo.failedTest()); + } + + protected void printDefectTrace(TestFailure booBoo) { + getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace())); + } + + protected void printFooter(TestResult result) { + if (result.wasSuccessful()) { + getWriter().println(); + getWriter().print("OK"); + getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")"); + + } else { + getWriter().println(); + getWriter().println("FAILURES!!!"); + getWriter().println("Tests run: "+result.runCount()+ + ", Failures: "+result.failureCount()+ + ", Errors: "+result.errorCount()); + } + getWriter().println(); + } + + + /** + * Returns the formatted string of the elapsed time. + * Duplicated from BaseTestRunner. Fix it. + */ + protected String elapsedTimeAsString(long runTime) { + // The following line was altered for compatibility with + // Android libraries. + return Double.toString((double)runTime/1000); + } + + public PrintStream getWriter() { + return fWriter; + } + /** + * @see junit.framework.TestListener#addError(Test, Throwable) + */ + public void addError(Test test, Throwable t) { + getWriter().print("E"); + } + + /** + * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError) + */ + public void addFailure(Test test, AssertionFailedError t) { + getWriter().print("F"); + } + + /** + * @see junit.framework.TestListener#endTest(Test) + */ + public void endTest(Test test) { + } + + /** + * @see junit.framework.TestListener#startTest(Test) + */ + public void startTest(Test test) { + getWriter().print("."); + if (fColumn++ >= 40) { + getWriter().println(); + fColumn= 0; + } + } } diff --git a/test-runner/src/junit/textui/TestRunner.java b/test-runner/src/junit/textui/TestRunner.java index 8bdc325..e955e0e 100644 --- a/test-runner/src/junit/textui/TestRunner.java +++ b/test-runner/src/junit/textui/TestRunner.java @@ -3,187 +3,201 @@ package junit.textui; import java.io.PrintStream; -import junit.framework.*; -import junit.runner.*; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestResult; +import junit.framework.TestSuite; +import junit.runner.BaseTestRunner; +import junit.runner.Version; /** * A command line based tool to run tests. * <pre> * java junit.textui.TestRunner [-wait] TestCaseClass * </pre> - * TestRunner expects the name of a TestCase class as argument. - * If this class defines a static <code>suite</code> method it - * will be invoked and the returned test is run. Otherwise all + * + * <p>TestRunner expects the name of a TestCase class as argument. + * If this class defines a static <code>suite</code> method it + * will be invoked and the returned test is run. Otherwise all * the methods starting with "test" having no arguments are run. * <p> * When the wait command line argument is given TestRunner * waits until the users types RETURN. * <p> * TestRunner prints a trace as the tests are executed followed by a - * summary at the end. + * summary at the end. */ public class TestRunner extends BaseTestRunner { - private ResultPrinter fPrinter; - - public static final int SUCCESS_EXIT= 0; - public static final int FAILURE_EXIT= 1; - public static final int EXCEPTION_EXIT= 2; - - /** - * Constructs a TestRunner. - */ - public TestRunner() { - this(System.out); - } - - /** - * Constructs a TestRunner using the given stream for all the output - */ - public TestRunner(PrintStream writer) { - this(new ResultPrinter(writer)); - } - - /** - * Constructs a TestRunner using the given ResultPrinter all the output - */ - public TestRunner(ResultPrinter printer) { - fPrinter= printer; - } - - /** - * Runs a suite extracted from a TestCase subclass. - */ - static public void run(Class testClass) { - run(new TestSuite(testClass)); - } - - /** - * Runs a single test and collects its results. - * This method can be used to start a test run - * from your program. - * <pre> - * public static void main (String[] args) { - * test.textui.TestRunner.run(suite()); - * } - * </pre> - */ - static public TestResult run(Test test) { - TestRunner runner= new TestRunner(); - return runner.doRun(test); - } - - /** - * Runs a single test and waits until the user - * types RETURN. - */ - static public void runAndWait(Test suite) { - TestRunner aTestRunner= new TestRunner(); - aTestRunner.doRun(suite, true); - } - - /** - * Always use the StandardTestSuiteLoader. Overridden from - * BaseTestRunner. - */ - public TestSuiteLoader getLoader() { - return new StandardTestSuiteLoader(); - } - - public void testFailed(int status, Test test, Throwable t) { - } - - public void testStarted(String testName) { - } - - public void testEnded(String testName) { - } - - /** - * Creates the TestResult to be used for the test run. - */ - protected TestResult createTestResult() { - return new TestResult(); - } - - public TestResult doRun(Test test) { - return doRun(test, false); - } - - public TestResult doRun(Test suite, boolean wait) { - TestResult result= createTestResult(); - result.addListener(fPrinter); - long startTime= System.currentTimeMillis(); - suite.run(result); - long endTime= System.currentTimeMillis(); - long runTime= endTime-startTime; - fPrinter.print(result, runTime); - - pause(wait); - return result; - } - - protected void pause(boolean wait) { - if (!wait) return; - fPrinter.printWaitPrompt(); - try { - System.in.read(); - } - catch(Exception e) { - } - } - - public static void main(String args[]) { - TestRunner aTestRunner= new TestRunner(); - try { - TestResult r= aTestRunner.start(args); - if (!r.wasSuccessful()) - System.exit(FAILURE_EXIT); - System.exit(SUCCESS_EXIT); - } catch(Exception e) { - System.err.println(e.getMessage()); - System.exit(EXCEPTION_EXIT); - } - } - - /** - * Starts a test run. Analyzes the command line arguments - * and runs the given test suite. - */ - protected TestResult start(String args[]) throws Exception { - String testCase= ""; - boolean wait= false; - - for (int i= 0; i < args.length; i++) { - if (args[i].equals("-wait")) - wait= true; - else if (args[i].equals("-c")) - testCase= extractClassName(args[++i]); - else if (args[i].equals("-v")) - System.err.println("JUnit "+Version.id()+" by Kent Beck and Erich Gamma"); - else - testCase= args[i]; - } - - if (testCase.equals("")) - throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class"); - - try { - Test suite= getTest(testCase); - return doRun(suite, wait); - } - catch(Exception e) { - throw new Exception("Could not create and run test suite: "+e); - } - } - - protected void runFailed(String message) { - System.err.println(message); - System.exit(FAILURE_EXIT); - } - - public void setPrinter(ResultPrinter printer) { - fPrinter= printer; - } - - + private ResultPrinter fPrinter; + + public static final int SUCCESS_EXIT= 0; + public static final int FAILURE_EXIT= 1; + public static final int EXCEPTION_EXIT= 2; + + /** + * Constructs a TestRunner. + */ + public TestRunner() { + this(System.out); + } + + /** + * Constructs a TestRunner using the given stream for all the output + */ + public TestRunner(PrintStream writer) { + this(new ResultPrinter(writer)); + } + + /** + * Constructs a TestRunner using the given ResultPrinter all the output + */ + public TestRunner(ResultPrinter printer) { + fPrinter= printer; + } + + /** + * Runs a suite extracted from a TestCase subclass. + */ + static public void run(Class<? extends TestCase> testClass) { + run(new TestSuite(testClass)); + } + + /** + * Runs a single test and collects its results. + * This method can be used to start a test run + * from your program. + * <pre> + * public static void main (String[] args) { + * test.textui.TestRunner.run(suite()); + * } + * </pre> + */ + static public TestResult run(Test test) { + TestRunner runner= new TestRunner(); + return runner.doRun(test); + } + + /** + * Runs a single test and waits until the user + * types RETURN. + */ + static public void runAndWait(Test suite) { + TestRunner aTestRunner= new TestRunner(); + aTestRunner.doRun(suite, true); + } + + @Override + public void testFailed(int status, Test test, Throwable t) { + } + + @Override + public void testStarted(String testName) { + } + + @Override + public void testEnded(String testName) { + } + + /** + * Creates the TestResult to be used for the test run. + */ + protected TestResult createTestResult() { + return new TestResult(); + } + + public TestResult doRun(Test test) { + return doRun(test, false); + } + + public TestResult doRun(Test suite, boolean wait) { + TestResult result= createTestResult(); + result.addListener(fPrinter); + long startTime= System.currentTimeMillis(); + suite.run(result); + long endTime= System.currentTimeMillis(); + long runTime= endTime-startTime; + fPrinter.print(result, runTime); + + pause(wait); + return result; + } + + protected void pause(boolean wait) { + if (!wait) return; + fPrinter.printWaitPrompt(); + try { + System.in.read(); + } + catch(Exception e) { + } + } + + public static void main(String args[]) { + TestRunner aTestRunner= new TestRunner(); + try { + TestResult r= aTestRunner.start(args); + if (!r.wasSuccessful()) + System.exit(FAILURE_EXIT); + System.exit(SUCCESS_EXIT); + } catch(Exception e) { + System.err.println(e.getMessage()); + System.exit(EXCEPTION_EXIT); + } + } + + /** + * Starts a test run. Analyzes the command line arguments + * and runs the given test suite. + */ + public TestResult start(String args[]) throws Exception { + String testCase= ""; + String method= ""; + boolean wait= false; + + for (int i= 0; i < args.length; i++) { + if (args[i].equals("-wait")) + wait= true; + else if (args[i].equals("-c")) + testCase= extractClassName(args[++i]); + else if (args[i].equals("-m")) { + String arg= args[++i]; + int lastIndex= arg.lastIndexOf('.'); + testCase= arg.substring(0, lastIndex); + method= arg.substring(lastIndex + 1); + } else if (args[i].equals("-v")) + System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma"); + else + testCase= args[i]; + } + + if (testCase.equals("")) + throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class"); + + try { + if (!method.equals("")) + return runSingleMethod(testCase, method, wait); + Test suite= getTest(testCase); + return doRun(suite, wait); + } catch (Exception e) { + throw new Exception("Could not create and run test suite: " + e); + } + } + + protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception { + Class<? extends TestCase> testClass= loadSuiteClass(testCase).asSubclass(TestCase.class); + Test test= TestSuite.createTest(testClass, method); + return doRun(test, wait); + } + + @Override + protected void runFailed(String message) { + System.err.println(message); + System.exit(FAILURE_EXIT); + } + + public void setPrinter(ResultPrinter printer) { + fPrinter= printer; + } + + } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java index d151d9e..77c0a3f 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java @@ -168,7 +168,7 @@ public class TestShellActivity extends Activity implements LayoutTestController } // This is asynchronous, but it gets processed by WebCore before it starts loading pages. - mWebViewClassic.useMockDeviceOrientation(); + mWebViewClassic.setUseMockDeviceOrientation(); } @Override diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java index fc22472..f958ade 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java @@ -394,7 +394,7 @@ public class LayoutTestsExecutor extends Activity { webViewSettings.setPageCacheCapacity(0); // This is asynchronous, but it gets processed by WebCore before it starts loading pages. - WebViewClassic.fromWebView(mCurrentWebView).useMockDeviceOrientation(); + WebViewClassic.fromWebView(mCurrentWebView).setUseMockDeviceOrientation(); // Must do this after setting the AppCache path. WebStorage.getInstance().deleteAllData(); diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java index 22e1bff..7105f2d 100644 --- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java @@ -79,6 +79,7 @@ public class RSTestCore { unitTests.add(new UT_atomic(this, mRes, mCtx)); unitTests.add(new UT_struct(this, mRes, mCtx)); unitTests.add(new UT_math(this, mRes, mCtx)); + unitTests.add(new UT_math_conformance(this, mRes, mCtx)); unitTests.add(new UT_mesh(this, mRes, mCtx)); unitTests.add(new UT_element(this, mRes, mCtx)); unitTests.add(new UT_sampler(this, mRes, mCtx)); diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java index 3e2a2ca..f52fe6f 100644 --- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_element.java @@ -108,7 +108,7 @@ public class UT_element extends UnitTest { _RS_ASSERT("complexElemsimpleElem.getDataType() == NONE", complexElem.getDataType() == DataType.NONE); _RS_ASSERT("complexElem.getSizeBytes() == ScriptField_ComplexStruct.Item.sizeof", - complexElem.getSizeBytes() == ScriptField_ComplexStruct.Item.sizeof); + complexElem.getBytesSize() == ScriptField_ComplexStruct.Item.sizeof); for (int i = 0; i < subElemCount; i ++) { _RS_ASSERT("complexElem.getSubElement(i) != null", diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_conformance.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_conformance.java new file mode 100644 index 0000000..f256a3a --- /dev/null +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_conformance.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; + +public class UT_math_conformance extends UnitTest { + private Resources mRes; + + protected UT_math_conformance(RSTestCore rstc, Resources res, Context ctx) { + super(rstc, "Math Conformance", ctx); + mRes = res; + } + + public void run() { + RenderScript pRS = RenderScript.create(mCtx); + ScriptC_math_conformance s = + new ScriptC_math_conformance(pRS, mRes, R.raw.math_conformance); + pRS.setMessageHandler(mRsMessage); + s.invoke_math_conformance_test(); + pRS.finish(); + waitForMessage(); + pRS.destroy(); + passTest(); + } +} diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java index 1de4d71..ca54ac4 100644 --- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_raster.java @@ -60,13 +60,13 @@ public class UT_program_raster extends UnitTest { } private void testJavaSide(RenderScript RS) { - _RS_ASSERT("pointSpriteEnabled.getPointSpriteEnabled() == true", - pointSpriteEnabled.getPointSpriteEnabled() == true); + _RS_ASSERT("pointSpriteEnabled.isPointSpriteEnabled() == true", + pointSpriteEnabled.isPointSpriteEnabled() == true); _RS_ASSERT("pointSpriteEnabled.getCullMode() == ProgramRaster.CullMode.BACK", pointSpriteEnabled.getCullMode() == ProgramRaster.CullMode.BACK); - _RS_ASSERT("cullMode.getPointSpriteEnabled() == false", - cullMode.getPointSpriteEnabled() == false); + _RS_ASSERT("cullMode.isPointSpriteEnabled() == false", + cullMode.isPointSpriteEnabled() == false); _RS_ASSERT("cullMode.getCullMode() == ProgramRaster.CullMode.FRONT", cullMode.getCullMode() == ProgramRaster.CullMode.FRONT); } diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java index 72a401d..4410ee3 100644 --- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_program_store.java @@ -112,15 +112,15 @@ public class UT_program_store extends UnitTest { boolean B, boolean A, boolean dither) { - _RS_ASSERT("ps.getDepthMaskEnabled() == depthMask", ps.getDepthMaskEnabled() == depthMask); + _RS_ASSERT("ps.isDepthMaskEnabled() == depthMask", ps.isDepthMaskEnabled() == depthMask); _RS_ASSERT("ps.getDepthFunc() == df", ps.getDepthFunc() == df); _RS_ASSERT("ps.getBlendSrcFunc() == bsf", ps.getBlendSrcFunc() == bsf); _RS_ASSERT("ps.getBlendDstFunc() == bdf", ps.getBlendDstFunc() == bdf); - _RS_ASSERT("ps.getColorMaskREnabled() == R", ps.getColorMaskREnabled() == R); - _RS_ASSERT("ps.getColorMaskGEnabled() == G", ps.getColorMaskGEnabled() == G); - _RS_ASSERT("ps.getColorMaskBEnabled() == B", ps.getColorMaskBEnabled() == B); - _RS_ASSERT("ps.getColorMaskAEnabled() == A", ps.getColorMaskAEnabled() == A); - _RS_ASSERT("ps.getDitherEnabled() == dither", ps.getDitherEnabled() == dither); + _RS_ASSERT("ps.isColorMaskRedEnabled() == R", ps.isColorMaskRedEnabled() == R); + _RS_ASSERT("ps.isColorMaskGreenEnabled() == G", ps.isColorMaskGreenEnabled() == G); + _RS_ASSERT("ps.isColorMaskBlueEnabled () == B", ps.isColorMaskBlueEnabled () == B); + _RS_ASSERT("ps.isColorMaskAlphaEnabled() == A", ps.isColorMaskAlphaEnabled() == A); + _RS_ASSERT("ps.isDitherEnabled() == dither", ps.isDitherEnabled() == dither); } void varyBuilderColorAndDither(ProgramStore.Builder pb, diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/math_conformance.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_conformance.rs new file mode 100644 index 0000000..2d62f34 --- /dev/null +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_conformance.rs @@ -0,0 +1,57 @@ +#include "shared.rsh" + +// Testing math conformance + +static bool test_rootn() { + bool failed = false; + + // rootn(x, 0) -> NaN + _RS_ASSERT(isnan(rootn(1.0f, 0))); + + // rootn(+/-0, n) -> +/-inf for odd n < 0 + _RS_ASSERT(isposinf(rootn(0.f, -3))); + _RS_ASSERT(isneginf(rootn(-0.f, -3))); + + // rootn(+/-0, n) -> +inf for even n < 0 + _RS_ASSERT(isposinf(rootn(0.f, -8))); + _RS_ASSERT(isposinf(rootn(-0.f, -8))); + + // rootn(+/-0, n) -> +/-0 for odd n > 0 + _RS_ASSERT(isposzero(rootn(0.f, 3))); + _RS_ASSERT(isnegzero(rootn(-0.f, 3))); + + // rootn(+/-0, n) -> +0 for even n > 0 + _RS_ASSERT(isposzero(rootn(0.f, 8))); + _RS_ASSERT(isposzero(rootn(-0.f, 8))); + + // rootn(x, n) -> NaN for x < 0 and even n + _RS_ASSERT(isnan(rootn(-10000.f, -4))); + _RS_ASSERT(isnan(rootn(-10000.f, 4))); + + // rootn(x, n) -> value for x < 0 and odd n + _RS_ASSERT(!isnan(rootn(-10000.f, -3))); + _RS_ASSERT(!isnan(rootn(-10000.f, 3))); + + if (failed) { + rsDebug("test_rootn FAILED", -1); + } + else { + rsDebug("test_rootn PASSED", 0); + } + + return failed; +} + +void math_conformance_test() { + bool failed = false; + failed |= test_rootn(); + + if (failed) { + rsDebug("math_conformance_test FAILED", -1); + rsSendToClientBlocking(RS_MSG_TEST_FAILED); + } + else { + rsDebug("math_conformance_test PASSED", 0); + rsSendToClientBlocking(RS_MSG_TEST_PASSED); + } +} diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh b/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh index 21be9af..8cdf0d8 100644 --- a/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh +++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/shared.rsh @@ -32,6 +32,48 @@ do { \ \ } while (0) +static const int iposinf = 0x7f800000; +static const int ineginf = 0xff800000; + +static const float posinf() { + float f = *((float*)&iposinf); + return f; +} + +static const float neginf() { + float f = *((float*)&ineginf); + return f; +} + +static bool isposinf(float f) { + int i = *((int*)(void*)&f); + return (i == iposinf); +} + +static bool isneginf(float f) { + int i = *((int*)(void*)&f); + return (i == ineginf); +} + +static bool isnan(float f) { + int i = *((int*)(void*)&f); + return (((i & 0x7f800000) == 0x7f800000) && (i & 0x007fffff)); +} + +static bool isposzero(float f) { + int i = *((int*)(void*)&f); + return (i == 0x00000000); +} + +static bool isnegzero(float f) { + int i = *((int*)(void*)&f); + return (i == 0x80000000); +} + +static bool iszero(float f) { + return isposzero(f) || isnegzero(f); +} + /* These constants must match those in UnitTest.java */ static const int RS_MSG_TEST_PASSED = 100; static const int RS_MSG_TEST_FAILED = 101; diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 689aa8e..cbd591f 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -345,6 +345,7 @@ enum { LABEL_ATTR = 0x01010001, ICON_ATTR = 0x01010002, NAME_ATTR = 0x01010003, + DEBUGGABLE_ATTR = 0x0101000f, VERSION_CODE_ATTR = 0x0101021b, VERSION_NAME_ATTR = 0x0101021c, SCREEN_ORIENTATION_ATTR = 0x0101001e, @@ -830,6 +831,15 @@ int doDump(Bundle* bundle) if (testOnly != 0) { printf("testOnly='%d'\n", testOnly); } + + int32_t debuggable = getResolvedIntegerAttribute(&res, tree, DEBUGGABLE_ATTR, &error, 0); + if (error != "") { + fprintf(stderr, "ERROR getting 'android:debuggable' attribute: %s\n", error.string()); + goto bail; + } + if (debuggable != 0) { + printf("application-debuggable\n"); + } } else if (tag == "uses-sdk") { int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); if (error != "") { diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp index 3cc2467..563225e 100644 --- a/tools/validatekeymaps/Main.cpp +++ b/tools/validatekeymaps/Main.cpp @@ -78,7 +78,7 @@ static bool validateFile(const char* filename) { return false; case FILETYPE_KEYLAYOUT: { - KeyLayoutMap* map; + sp<KeyLayoutMap> map; status_t status = KeyLayoutMap::load(String8(filename), &map); if (status) { fprintf(stderr, "Error %d parsing key layout file.\n\n", status); @@ -88,7 +88,7 @@ static bool validateFile(const char* filename) { } case FILETYPE_KEYCHARACTERMAP: { - KeyCharacterMap* map; + sp<KeyCharacterMap> map; status_t status = KeyCharacterMap::load(String8(filename), &map); if (status) { fprintf(stderr, "Error %d parsing key character map file.\n\n", status); @@ -104,6 +104,7 @@ static bool validateFile(const char* filename) { fprintf(stderr, "Error %d parsing input device configuration file.\n\n", status); return false; } + delete map; break; } @@ -114,6 +115,7 @@ static bool validateFile(const char* filename) { fprintf(stderr, "Error %d parsing virtual key definition file.\n\n", status); return false; } + delete map; break; } } diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index ca593c1..4ec2e02 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -397,11 +397,25 @@ public class WifiNative { } } + public boolean startWpsPbc(String iface, String bssid) { + if (TextUtils.isEmpty(bssid)) { + return doBooleanCommand("WPS_PBC interface=" + iface); + } else { + return doBooleanCommand("WPS_PBC interface=" + iface + " " + bssid); + } + } + public boolean startWpsPinKeypad(String pin) { if (TextUtils.isEmpty(pin)) return false; return doBooleanCommand("WPS_PIN any " + pin); } + public boolean startWpsPinKeypad(String iface, String pin) { + if (TextUtils.isEmpty(pin)) return false; + return doBooleanCommand("WPS_PIN interface=" + iface + " any " + pin); + } + + public String startWpsPinDisplay(String bssid) { if (TextUtils.isEmpty(bssid)) { return doStringCommand("WPS_PIN any"); @@ -410,6 +424,14 @@ public class WifiNative { } } + public String startWpsPinDisplay(String iface, String bssid) { + if (TextUtils.isEmpty(bssid)) { + return doStringCommand("WPS_PIN interface=" + iface + " any"); + } else { + return doStringCommand("WPS_PIN interface=" + iface + " " + bssid); + } + } + /* Configures an access point connection */ public boolean startWpsRegistrar(String bssid, String pin) { if (TextUtils.isEmpty(bssid) || TextUtils.isEmpty(pin)) return false; @@ -441,6 +463,26 @@ public class WifiNative { return doBooleanCommand("SET p2p_ssid_postfix " + postfix); } + public boolean setP2pGroupIdle(String iface, int time) { + return doBooleanCommand("SET interface=" + iface + " p2p_group_idle " + time); + } + + public boolean setP2pPowerSave(String iface, boolean enabled) { + if (enabled) { + return doBooleanCommand("P2P_SET interface=" + iface + " ps 1"); + } else { + return doBooleanCommand("P2P_SET interface=" + iface + " ps 0"); + } + } + + /** + * "sta" prioritizes STA connection over P2P and "p2p" prioritizes + * P2P connection over STA + */ + public boolean setConcurrencyPriority(String s) { + return doBooleanCommand("P2P_SET conc_priority " + s); + } + public boolean p2pFind() { return doBooleanCommand("P2P_FIND"); } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index d3caf90..314e33e 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -116,6 +116,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub { /* Set a two minute discover timeout to avoid STA scans from being blocked */ private static final int DISCOVER_TIMEOUT_S = 120; + /* Idle time after a peer is gone when the group is torn down */ + private static final int GROUP_IDLE_TIME_S = 2; + /** * Delay between restarts upon failure to setup connection with supplicant */ @@ -390,10 +393,21 @@ public class WifiP2pService extends IWifiP2pManager.Stub { case WifiMonitor.NETWORK_CONNECTION_EVENT: case WifiMonitor.NETWORK_DISCONNECTION_EVENT: case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: + case WifiMonitor.P2P_GROUP_REMOVED_EVENT: case PEER_CONNECTION_USER_ACCEPT: case PEER_CONNECTION_USER_REJECT: case GROUP_CREATING_TIMED_OUT: break; + /* unexpected group created, remove */ + case WifiMonitor.P2P_GROUP_STARTED_EVENT: + mGroup = (WifiP2pGroup) message.obj; + loge("Unexpected group creation, remove " + mGroup); + mWifiNative.p2pGroupRemove(mGroup.getInterface()); + break; + case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: + loge("Unexpected group failure, flush peers"); + mWifiNative.p2pFlush(); + break; default: loge("Unhandled message " + message); return NOT_HANDLED; @@ -553,6 +567,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { if (DBG) logd(getName()); sendP2pStateChangedBroadcast(true); mNetworkInfo.setIsAvailable(true); + sendP2pConnectionChangedBroadcast(); initializeP2pSettings(); } @@ -702,9 +717,11 @@ public class WifiP2pService extends IWifiP2pManager.Stub { //If peer is a GO, we do not need to send provisional discovery, //the supplicant takes care of it. if (mWifiNative.isGroupOwner(mSavedPeerConfig.deviceAddress)) { + if (DBG) logd("Sending join to GO"); p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP); transitionTo(mGroupNegotiationState); } else { + if (DBG) logd("Sending prov disc"); transitionTo(mProvisionDiscoveryState); } } @@ -792,9 +809,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { case GROUP_CREATING_TIMED_OUT: if (mGroupCreatingTimeoutIndex == message.arg1) { if (DBG) logd("Group negotiation timed out"); - updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.FAILED); - mSavedPeerConfig = null; - sendP2pPeersChangedBroadcast(); + handleGroupCreationFailure(); transitionTo(mInactiveState); } break; @@ -804,12 +819,15 @@ public class WifiP2pService extends IWifiP2pManager.Stub { WifiP2pManager.BUSY); break; case WifiP2pManager.CANCEL_CONNECT: - if (mWifiNative.p2pCancelConnect()) { - replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); - } else { - replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, - WifiP2pManager.ERROR); - } + //Do a supplicant p2p_cancel which only cancels an ongoing + //group negotiation. This will fail for a pending provision + //discovery or for a pending user action, but at the framework + //level, we always treat cancel as succeded and enter + //an inactive state + mWifiNative.p2pCancelConnect(); + handleGroupCreationFailure(); + transitionTo(mInactiveState); + replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); break; default: return NOT_HANDLED; @@ -952,9 +970,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: if (DBG) logd(getName() + " go failure"); - updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.FAILED); - mSavedPeerConfig = null; - sendP2pPeersChangedBroadcast(); + handleGroupCreationFailure(); transitionTo(mInactiveState); break; default: @@ -979,6 +995,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub { setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS); sendP2pConnectionChangedBroadcast(); } + + if (!mPersistGroup) { + mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S); + } } @Override @@ -1027,6 +1047,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { if (DBG) logd("DhcpInfo: " + dhcpInfo); setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress); sendP2pConnectionChangedBroadcast(); + //Turn on power save on client + mWifiNative.setP2pPowerSave(mGroup.getInterface(), true); } else { loge("DHCP failed"); mWifiNative.p2pGroupRemove(mGroup.getInterface()); @@ -1399,6 +1421,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { //The supplicant default is to support everything, but a bug necessitates //the framework to specify this explicitly mWifiNative.setConfigMethods("keypad display push_button"); + //STA has higher priority over P2P + mWifiNative.setConcurrencyPriority("sta"); mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress(); updateThisDevice(WifiP2pDevice.AVAILABLE); @@ -1416,6 +1440,14 @@ public class WifiP2pService extends IWifiP2pManager.Stub { sendThisDeviceChangedBroadcast(); } + private void handleGroupCreationFailure() { + mSavedPeerConfig = null; + /* After cancelling group formation, new connections on existing peers can fail + * at supplicant. Flush and restart discovery */ + mWifiNative.p2pFlush(); + sendMessage(WifiP2pManager.DISCOVER_PEERS); + } + //State machine initiated requests can have replyTo set to null indicating //there are no recepients, we ignore those reply actions private void replyToMessage(Message msg, int what) { |
