Merge "Synchronize/align periodic sync alarms based on a random per device seed value."
diff --git a/api/current.txt b/api/current.txt
index 3b0b95b..ee964f7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -102,6 +102,7 @@
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";
@@ -22268,6 +22269,7 @@
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
@@ -22327,7 +22329,8 @@
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);
@@ -22342,10 +22345,12 @@
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
@@ -23529,6 +23534,10 @@
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);
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 @@
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 @@
}
}
+ /**
+ * 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 @@
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/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 @@
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 @@
* <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/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 @@
}
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 @@
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 @@
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/content/SyncManager.java b/core/java/android/content/SyncManager.java
index cb3d9cf..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.Maps;
import android.accounts.Account;
+import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
import android.accounts.AccountManagerService;
import android.accounts.OnAccountsUpdateListener;
@@ -240,22 +241,14 @@
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);
}
}
@@ -341,33 +334,6 @@
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) {
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 5ab9e5a..d821918 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -25,7 +25,7 @@
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;
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 @@
// 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 @@
public final class InputManager {
private static final String TAG = "InputManager";
- private static final IInputManager sIm;
+ private static InputManager sInstance;
- private final Context mContext;
-
- // 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 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 @@
* </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 @@
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 @@
*
* @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 @@
*
* @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;
+ mIm.setKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not set keyboard layout for input device.", ex);
}
- 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;
}
/**
@@ -359,15 +266,16 @@
* 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 @@
* 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 @@
}
try {
- sIm.tryPointerSpeed(speed);
+ mIm.tryPointerSpeed(speed);
} catch (RemoteException ex) {
Log.w(TAG, "Could not set temporary pointer speed.", ex);
}
@@ -424,12 +333,27 @@
*
* @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 @@
*
* @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 @@
*
* @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 @@
*
* @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 @@
}
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/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index aa0ac74..8bc36b7 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -237,6 +237,17 @@
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,26 +1391,40 @@
}
@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;
- usePbufferSurface(managedContext.getContext());
- }
+ if (needsContext) {
+ Gl20RendererEglContext managedContext =
+ (Gl20RendererEglContext) sEglContextStorage.get();
+ if (managedContext == null) return false;
+ usePbufferSurface(managedContext.getContext());
+ }
- destroyResources(view);
- GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
-
+ try {
+ action.run();
+ } finally {
if (needsContext) {
sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
}
+
+ 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);
+ }
+ });
+ }
}
private static void destroyResources(View view) {
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 @@
* </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 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 @@
* @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 @@
* @return The input device ids.
*/
public static int[] getDeviceIds() {
- return InputManager.getInputDeviceIds();
+ return InputManager.getInstance().getInputDeviceIds();
}
/**
@@ -356,6 +390,22 @@
}
/**
+ * 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 @@
* @return The key character map.
*/
public KeyCharacterMap getKeyCharacterMap() {
- return KeyCharacterMap.load(mId);
- }
-
- String getKeyCharacterMapFile() {
- return mKeyCharacterMapFile;
+ return mKeyCharacterMap;
}
/**
@@ -453,6 +499,7 @@
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 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 @@
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 @@
}
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 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 @@
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(int deviceId, int ptr) {
- mDeviceId = deviceId;
+ 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.");
+ }
+ }
+
+ // Called from native
+ private KeyCharacterMap(int ptr) {
mPtr = ptr;
}
@@ -174,33 +195,16 @@
* 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 @@
if (chars == null) {
throw new IllegalArgumentException("chars must not be null.");
}
- return nativeGetEvents(mPtr, mDeviceId, chars);
+ return nativeGetEvents(mPtr, chars);
}
/**
@@ -527,7 +531,7 @@
* @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 @@
* 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 @@
}
/**
+ * 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 @@
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..ba62e65 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -204,7 +204,18 @@
@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..0be7a87 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8698,7 +8698,7 @@
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
- invalidate(true);
+ postInvalidateOnAnimation();
}
}
}
@@ -8852,7 +8852,7 @@
if (invalidate) {
// Invalidate to show the scrollbars
- invalidate(true);
+ postInvalidateOnAnimation();
}
if (scrollCache.state == ScrollabilityCache.OFF) {
@@ -9212,6 +9212,9 @@
* @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 +9244,9 @@
* 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 +9267,8 @@
*
* @param action The Runnable that will be executed.
*
- * @hide
+ * @see #postOnAnimationDelayed
+ * @see #removeCallbacks
*/
public void postOnAnimation(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
@@ -9286,7 +9293,8 @@
* @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 +9319,11 @@
* 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 +9348,7 @@
* only when this View is attached to a window.</p>
*
* @see #invalidate()
+ * @see #postInvalidateDelayed(long)
*/
public void postInvalidate() {
postInvalidateDelayed(0);
@@ -9354,6 +9368,7 @@
*
* @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 +9383,9 @@
*
* @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 +9409,10 @@
* @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 +9439,7 @@
* <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 +9462,8 @@
* @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
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 9c955bd..5dc2681 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -57,6 +57,7 @@
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.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;
@@ -981,6 +981,8 @@
/**
* 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;
@@ -994,35 +996,10 @@
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;
@@ -1410,7 +1387,7 @@
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;
@@ -1500,6 +1477,68 @@
}
+ 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;
@@ -2869,7 +2908,7 @@
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;
@@ -4372,8 +4411,7 @@
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);
@@ -5573,7 +5611,6 @@
addAccessibilityApisToJavaScript();
- mTouchEventQueue.reset();
updateHwAccelerated();
}
@@ -5822,20 +5859,6 @@
*/
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;
}
@@ -5905,23 +5928,17 @@
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) {
@@ -5931,12 +5948,14 @@
}
/*
- * 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
@@ -5952,7 +5971,6 @@
switch (action) {
case MotionEvent.ACTION_DOWN: {
- mPreventDefault = PREVENT_DEFAULT_NO;
mConfirmMove = false;
mInitialHitTestResult = null;
if (!mEditTextScroller.isFinished()) {
@@ -5972,20 +5990,11 @@
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;
@@ -5999,19 +6008,6 @@
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);
@@ -6058,43 +6054,6 @@
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) {
@@ -6104,13 +6063,11 @@
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;
}
@@ -6149,48 +6106,16 @@
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 &&
@@ -6201,19 +6126,9 @@
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
@@ -6239,10 +6154,9 @@
}
// do pan
- boolean done = false;
boolean keepScrollBarsVisible = false;
if (deltaX == 0 && deltaY == 0) {
- keepScrollBarsVisible = done = true;
+ keepScrollBarsVisible = true;
} else {
mAverageAngle +=
(calculateDragAngle(deltaX, deltaY) - mAverageAngle)
@@ -6319,7 +6233,7 @@
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);
}
@@ -6332,24 +6246,6 @@
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;
@@ -6358,66 +6254,14 @@
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) {
@@ -6432,8 +6276,6 @@
mPrivateHandler.sendEmptyMessageDelayed(
RELEASE_SINGLE_TAP, ViewConfiguration
.getDoubleTapTimeout());
- } else {
- doShortPress();
}
break;
}
@@ -6446,13 +6288,9 @@
// 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
@@ -6491,128 +6329,10 @@
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);
- }
-
- 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() + ")");
- }
-
- 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();
- }
- }
- }
-
- 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));
- }
-
- 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();
- }
- }
}
private void startTouch(float x, float y, long eventTime) {
@@ -7249,39 +6969,6 @@
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.
@@ -7569,485 +7256,6 @@
return Math.max(0, mEditTextContent.height() - mEditTextContentBounds.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;
- }
- }
- }
- }
- }
-
//-------------------------------------------------------------------------
// Methods can be called from a separate thread, like WebViewCore
// If it needs to call the View system, it has to send message.
@@ -8056,7 +7264,7 @@
/**
* 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
@@ -8097,20 +7305,6 @@
((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;
@@ -8126,48 +7320,6 @@
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)
@@ -8225,6 +7377,8 @@
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
@@ -8281,20 +7435,7 @@
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:
@@ -8559,6 +7700,21 @@
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) {
@@ -9440,13 +8596,11 @@
&& 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 ec2cd5c..6390ffe 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -40,6 +40,7 @@
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 @@
return mBrowserFrame;
}
+ public WebKitCallbacks getInputDispatcherCallbacks() {
+ return mEventHub;
+ }
+
//-------------------------------------------------------------------------
// Common methods
//-------------------------------------------------------------------------
@@ -595,11 +600,6 @@
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);
@@ -663,6 +663,7 @@
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,
@@ -1025,8 +1026,8 @@
"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
@@ -1051,7 +1052,7 @@
/**
* @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;
@@ -1096,11 +1097,6 @@
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.
@@ -1115,9 +1111,6 @@
// 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
@@ -1266,10 +1259,6 @@
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.
@@ -1502,45 +1491,6 @@
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;
@@ -1824,6 +1774,38 @@
}
}
+ @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
*/
@@ -2154,7 +2136,6 @@
// 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;
@@ -2200,25 +2181,6 @@
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;
@@ -2394,15 +2356,6 @@
}
}
- // 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) {
diff --git a/core/java/android/webkit/WebViewInputDispatcher.java b/core/java/android/webkit/WebViewInputDispatcher.java
new file mode 100644
index 0000000..e7024d9
--- /dev/null
+++ b/core/java/android/webkit/WebViewInputDispatcher.java
@@ -0,0 +1,1151 @@
+/*
+ * 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);
+ }
+ }
+
+ 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/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 @@
/**
* 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 @@
}
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 @@
}
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 @@
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 @@
}
// Remember where the motion event started
- mLastMotionX = ev.getX();
+ mLastMotionX = (int) ev.getX();
mActivePointerId = ev.getPointerId(0);
break;
}
@@ -558,7 +558,7 @@
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 @@
}
if (mEdgeGlowLeft != null
&& (!mEdgeGlowLeft.isFinished() || !mEdgeGlowRight.isFinished())) {
- invalidate();
+ postInvalidateOnAnimation();
}
}
}
@@ -608,7 +608,7 @@
} else {
if (mScroller.springBack(mScrollX, mScrollY, 0,
getScrollRange(), 0, 0)) {
- invalidate();
+ postInvalidateOnAnimation();
}
}
}
@@ -626,7 +626,7 @@
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 @@
// 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 @@
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 @@
}
if (!awakenScrollBars()) {
- invalidate();
+ postInvalidateOnAnimation();
}
}
}
@@ -1452,7 +1452,7 @@
newFocused.requestFocus(movingRight ? View.FOCUS_RIGHT : View.FOCUS_LEFT);
}
- invalidate();
+ postInvalidateOnAnimation();
}
}
@@ -1503,7 +1503,7 @@
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 @@
-(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/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 @@
/**
* 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 @@
}
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 @@
}
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 @@
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 @@
}
// Remember where the motion event started
- mLastMotionY = ev.getY();
+ mLastMotionY = (int) ev.getY();
mActivePointerId = ev.getPointerId(0);
break;
}
@@ -572,8 +572,8 @@
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 @@
}
if (mEdgeGlowTop != null
&& (!mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished())) {
- invalidate();
+ postInvalidateOnAnimation();
}
}
}
@@ -622,7 +622,7 @@
} else {
if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0,
getScrollRange())) {
- invalidate();
+ postInvalidateOnAnimation();
}
}
}
@@ -634,7 +634,7 @@
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 @@
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 @@
// 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 @@
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 @@
if (!awakenScrollBars()) {
// Keep on drawing until the animation has finished.
- invalidate();
+ postInvalidateOnAnimation();
}
} else {
if (mFlingStrictSpan != null) {
@@ -1430,7 +1430,7 @@
mFlingStrictSpan = StrictMode.enterCriticalSpan("ScrollView-fling");
}
- invalidate();
+ postInvalidateOnAnimation();
}
}
@@ -1495,7 +1495,7 @@
canvas.translate(mPaddingLeft, Math.min(0, scrollY));
mEdgeGlowTop.setSize(width, getHeight());
if (mEdgeGlowTop.draw(canvas)) {
- invalidate();
+ postInvalidateOnAnimation();
}
canvas.restoreToCount(restoreCount);
}
@@ -1509,7 +1509,7 @@
canvas.rotate(180, width, 0);
mEdgeGlowBottom.setSize(width, height);
if (mEdgeGlowBottom.draw(canvas)) {
- invalidate();
+ postInvalidateOnAnimation();
}
canvas.restoreToCount(restoreCount);
}
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 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 @@
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..879b9d2 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -148,7 +148,6 @@
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_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);
@@ -1082,7 +1083,8 @@
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_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 @@
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 @@
const char* getInputChannelName() {
return mInputConsumer.getChannel()->getName().string();
}
+
+ static int handleReceiveCallback(int receiveFd, int events, void* data);
};
@@ -128,11 +129,13 @@
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 @@
mBatchedInputEventPending = false;
}
- JNIEnv* env = AndroidRuntime::getJNIEnv();
+ bool skipCallbacks = false;
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
@@ -150,7 +153,8 @@
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 @@
#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 @@
}
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;
+ inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
+ static_cast<MotionEvent*>(inputEvent));
+ break;
- default:
- assert(false); // InputConsumer should prevent this from ever happening
- inputEventObj = NULL;
+ 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());
+#endif
+ 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 (!inputEventObj) {
- ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
- mInputConsumer.sendFinishedSignal(seq, false);
- continue;
- }
-
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
-#endif
- env->CallVoidMethod(mReceiverObjGlobal,
- gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
-
- env->DeleteLocalRef(inputEventObj);
-
- if (mMessageQueue->raiseAndClearException(env, "dispatchInputEvent")) {
+ if (skipCallbacks) {
mInputConsumer.sendFinishedSignal(seq, false);
}
}
@@ -268,8 +273,8 @@
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 @@
} 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 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 @@
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 @@
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 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 @@
(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 @@
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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3ee2377..f5c0f8f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -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/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/values-af/strings.xml b/core/res/res/values-af/strings.xml
index f23c7e2..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>
@@ -1059,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>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 871bf45..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>
@@ -1059,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>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9c3d658..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>
@@ -1059,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>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 9aab752..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>
@@ -1059,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>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 7d7c212..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>
@@ -1059,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>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 6c6030c..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>
@@ -1059,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>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index ca93327..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>
@@ -1059,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>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 2c7f1306..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>
@@ -1059,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>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f42f4d2..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>
@@ -1059,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>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index d85d639..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>
@@ -1059,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>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2ecc4ab..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>
@@ -1059,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>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 752f55d..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>
@@ -1059,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>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8ade0e0..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>
@@ -1059,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>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 0a8faed..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>
@@ -1059,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>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index c9329bb..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>
@@ -1059,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>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 8a1079b..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>
@@ -1059,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>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f05e564c..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>
@@ -1059,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>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 9a742c4..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>
@@ -1059,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>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index ba0fb7a..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>
@@ -1059,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>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d5c1602..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>
@@ -1059,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>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 65c24a9d..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>
@@ -1059,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>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 03cf404..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>
@@ -1059,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>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 3c6e0c2..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>
@@ -1059,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>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9e21085..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>
@@ -1059,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>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8dc3fa6..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>
@@ -1059,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>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index fa13981..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>
@@ -1059,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>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1fe5316..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>
@@ -1059,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>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index b1dd288..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>
@@ -1059,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>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ec580ad..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>
@@ -1059,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>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 94d9712..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>
@@ -1059,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>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index ce1dd58..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>
@@ -1059,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>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 2e71e81..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>
@@ -1059,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>
@@ -1173,7 +1181,7 @@
<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>
<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_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>
@@ -1206,13 +1214,13 @@
<string name="content_description_sliding_handle" msgid="415975056159262248">"Barra deslizante. Toque & não solte."</string>
<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 à esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
- <string name="description_direction_right" msgid="8034433242579600980">"Deslize para a direita <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>
- <string name="description_target_search" msgid="3091587249776033139">"Pesquisa"</string>
+ <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 f762192..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>
@@ -1059,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>
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 fbc5b24..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>
@@ -1059,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>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 041133cd..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>
@@ -1059,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>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ec890ce..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>
@@ -1059,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>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0cac188..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>
@@ -1059,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>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 94024b8..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>
@@ -1059,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>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ec77eb1..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>
@@ -1059,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>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index f7d738a0..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>
@@ -1059,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>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index a9313b7..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>
@@ -1059,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>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index db0befa..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>
@@ -1059,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>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 29cde7d..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>
@@ -1059,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>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f2ef429..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>
@@ -1059,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>
@@ -1173,18 +1181,18 @@
<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>
<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_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>
- <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="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>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 94ce574..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>
@@ -1059,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>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index fd69a3e..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>
@@ -1059,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>
@@ -1172,7 +1180,7 @@
<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>
- <string name="number_picker_increment_scroll_action" msgid="9101473045891835490">"向上滑动可增大值,向下滑动可减小值。"</string>
+ <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>
@@ -1181,8 +1189,8 @@
<string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"设置上午时间"</string>
<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_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>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9283fa9..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>
@@ -1059,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>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 7638a1a..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>
@@ -1059,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>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 31aa8d5..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
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index cbfc1a4..aaef701 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" />
@@ -1042,6 +1044,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" />
@@ -1449,6 +1452,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 +1475,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" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 44f2ade..0eb46bd 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>
diff --git a/docs/html/images/training/basics/intents-choice.png b/docs/html/images/training/basics/intents-choice.png
new file mode 100644
index 0000000..f99596d
--- /dev/null
+++ b/docs/html/images/training/basics/intents-choice.png
Binary files differ
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/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 @@
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 @@
* 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 @@
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 @@
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 @@
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..5408680 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,18 +57,21 @@
/**
* 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 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;
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 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..dd3ad1e9 100644
--- a/include/androidfw/VirtualKeyMap.h
+++ b/include/androidfw/VirtualKeyMap.h
@@ -43,6 +43,8 @@
/**
* 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 @@
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 @@
# 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 @@
}
}
-
-// --- 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 @@
// --- KeyCharacterMap ---
+sp<KeyCharacterMap> KeyCharacterMap::sEmpty = new KeyCharacterMap();
+
KeyCharacterMap::KeyCharacterMap() :
mType(KEYBOARD_TYPE_UNKNOWN) {
}
@@ -89,23 +96,23 @@
}
}
-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 @@
tokenizer->getFilename().string(), tokenizer->getLineNumber(),
elapsedTime / 1000000.0);
#endif
- if (status) {
- delete map;
- } else {
+ if (!status) {
*outMap = map;
}
}
@@ -124,6 +129,10 @@
return status;
}
+sp<KeyCharacterMap> KeyCharacterMap::empty() {
+ return sEmpty;
+}
+
int32_t KeyCharacterMap::getKeyboardType() const {
return mType;
}
@@ -419,6 +428,79 @@
}
}
+#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..1809412 100644
--- a/libs/androidfw/KeyLayoutMap.cpp
+++ b/libs/androidfw/KeyLayoutMap.cpp
@@ -47,23 +47,23 @@
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 @@
tokenizer->getFilename().string(), tokenizer->getLineNumber(),
elapsedTime / 1000000.0);
#endif
- if (status) {
- delete map;
- } else {
+ if (!status) {
*outMap = map;
}
}
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 @@
// --- 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 @@
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 @@
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/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2a908ab..06928df 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -249,6 +249,8 @@
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 @@
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);
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.net.Uri;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -57,7 +58,24 @@
* @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/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 @@
"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 @@
// 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/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/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 33aca928..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..ec92713c 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/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 @@
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 @@
if (closeKeyboard) {
mImm.hideSoftInputFromWindow(getWindowToken(), 0);
}
- updateHardKeyboardEnabled();
}
private void startActivity(Intent intent) {
@@ -329,6 +328,7 @@
mHardKeyboardSection.setVisibility(View.VISIBLE);
if (mHardKeyboardSwitch.isChecked() != mHardKeyboardEnabled) {
mHardKeyboardSwitch.setChecked(mHardKeyboardEnabled);
+ updateHardKeyboardEnabled();
}
} else {
mHardKeyboardSection.setVisibility(View.GONE);
diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
index 985dcd3..31fbaafd 100644
--- a/policy/src/com/android/internal/policy/impl/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
@@ -213,7 +213,8 @@
if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
mConnection,
- Context.BIND_AUTO_CREATE);
+ Context.BIND_AUTO_CREATE,
+ mLockPatternUtils.getCurrentUser());
if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
mBoundToService = true;
} else {
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 596040c..39ede89 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -703,6 +703,7 @@
@Override
public void onUserChanged(int userId) {
+ mFaceUnlock.stopAndUnbind();
mLockPatternUtils.setCurrentUser(userId);
updateScreen(getInitialMode(), true);
}
@@ -817,7 +818,9 @@
if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
boolean restartFaceLock = mFaceUnlock.stopIfRunning();
recreateUnlockScreen(unlockMode);
- if (restartFaceLock) mFaceUnlock.activateIfAble(mHasOverlay);
+ if (restartFaceLock) {
+ mFaceUnlock.activateIfAble(mHasOverlay);
+ }
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index d150b5c..1891146 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -327,7 +327,7 @@
RecentApplicationsDialog mRecentAppsDialog;
int mRecentAppsDialogHeldModifiers;
- int mLidOpen = LID_ABSENT;
+ int mLidState = LID_ABSENT;
boolean mSystemReady;
boolean mSystemBooted;
@@ -1225,16 +1225,16 @@
}
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;
@@ -2797,7 +2797,7 @@
if (mHeadless) return;
// lid changed state
- mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED;
+ mLidState = lidOpen ? LID_OPEN : LID_CLOSED;
updateKeyboardVisibility();
boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen);
@@ -3486,7 +3486,7 @@
}
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
@@ -3878,7 +3878,7 @@
}
private void updateKeyboardVisibility() {
- mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
+ mPowerManager.setKeyboardVisibility(mLidState == LID_OPEN);
}
void updateRotation(boolean alwaysSendConfiguration) {
@@ -4132,7 +4132,7 @@
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/input/EventHub.cpp b/services/input/EventHub.cpp
index 7060ae2..744f2ad 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -93,6 +93,32 @@
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);
+}
+
// --- Global Functions ---
uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
@@ -164,7 +190,7 @@
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 +282,7 @@
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 +333,7 @@
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 +348,7 @@
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 +373,7 @@
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 +391,7 @@
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",
@@ -421,7 +447,7 @@
}
}
- if (mBuiltInKeyboardId != -1) {
+ if (mBuiltInKeyboardId != NO_BUILT_IN_KEYBOARD) {
device = getDeviceLocked(mBuiltInKeyboardId);
if (device && device->keyMap.haveKeyLayout()) {
@@ -449,7 +475,7 @@
}
}
- if (mBuiltInKeyboardId != -1) {
+ if (mBuiltInKeyboardId != NO_BUILT_IN_KEYBOARD) {
device = getDeviceLocked(mBuiltInKeyboardId);
if (device && device->keyMap.haveKeyLayout()) {
@@ -494,7 +520,7 @@
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 +546,17 @@
}
}
-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 +604,7 @@
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;
@@ -813,6 +839,9 @@
if(res < 0) {
ALOGE("scan dir failed for %s\n", DEVICE_PATH);
}
+ if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
+ createVirtualKeyboardLocked();
+ }
}
// ----------------------------------------------------------------------------
@@ -908,29 +937,8 @@
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)) {
@@ -1048,7 +1056,7 @@
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;
@@ -1133,11 +1141,29 @@
toString(mBuiltInKeyboardId == deviceId),
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) {
@@ -1224,11 +1250,13 @@
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..c35df109 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>
@@ -43,6 +44,13 @@
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.
*/
@@ -107,6 +115,9 @@
/* 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,
};
@@ -208,7 +219,7 @@
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;
@@ -266,7 +277,7 @@
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 +293,7 @@
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 +316,15 @@
~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 +346,13 @@
// 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..42512d8 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -523,19 +523,21 @@
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;
+ }
}
}
@@ -1789,7 +1791,7 @@
InputMapper::populateDeviceInfo(info);
info->setKeyboardType(mKeyboardType);
- info->setKeyCharacterMapFile(getEventHub()->getKeyCharacterMapFile(getDeviceId()));
+ info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
}
void KeyboardInputMapper::dump(String8& dump) {
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 2cccf9f..057ad18 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -610,8 +610,8 @@
}
}
- 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 {
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index 16eeb7ba..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.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 @@
//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.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.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 @@
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 @@
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 @@
private AlertDialog.Builder mDialogBuilder;
private AlertDialog mSwitchingDialog;
+ private View mSwitchingDialogTitleView;
private InputMethodInfo[] mIms;
private int[] mSubtypeIds;
@@ -528,7 +537,31 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
}
}
}
-
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 @@
.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/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index bebce7e..2d2a881 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1795,7 +1795,7 @@
final boolean stateChanged = mPowerState != newState;
if (stateChanged && reason == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) {
- if (mPolicy.isScreenSaverEnabled()) {
+ if (mPolicy != null && mPolicy.isScreenSaverEnabled()) {
if (mSpew) {
Slog.d(TAG, "setPowerState: running screen saver instead of turning off screen");
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 68bbb571..241d04ff 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -276,7 +276,7 @@
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);
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 @@
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.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 @@
/** 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 @@
* 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 @@
}
}
- @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 @@
* @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 @@
* 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 @@
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 @@
}
}
}
+
+ 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/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 1198a77..0be6612 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -453,7 +453,7 @@
mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime);
}
if (mDimAnimator != null && mDimAnimator.mDimShown) {
- mAnimating |= mDimAnimator.updateSurface(mDimParams != null, mCurrentTime,
+ mAnimating |= mDimAnimator.updateSurface(isDimming(), mCurrentTime,
!mService.okToDisplay());
}
@@ -501,6 +501,10 @@
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 8d65dc3..f48b56d1 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3974,7 +3974,6 @@
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
@@ -3986,23 +3985,19 @@
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) {
@@ -4055,6 +4050,12 @@
delayed = true;
}
+ for (int i = wtoken.allAppWindows.size() - 1; i >= 0 && !delayed; i--) {
+ if (wtoken.allAppWindows.get(i).mWinAnimator.isWindowAnimating()) {
+ delayed = true;
+ }
+ }
+
return delayed;
}
@@ -4917,7 +4918,11 @@
// 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++) {
@@ -4953,7 +4958,8 @@
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,
@@ -4965,7 +4971,8 @@
// 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;
}
}
@@ -7262,6 +7269,7 @@
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:");
@@ -8021,16 +8029,18 @@
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);
}
}
}
@@ -8180,7 +8190,7 @@
updateWallpaperVisibilityLocked();
}
}
- if (!mInnerFields.mDimming && mAnimator.mDimParams != null) {
+ if (!mInnerFields.mDimming && mAnimator.isDimming()) {
mAnimator.stopDimming();
}
} catch (RuntimeException e) {
@@ -9331,7 +9341,7 @@
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) {
@@ -9533,4 +9543,9 @@
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/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index c137a78..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 @@
} 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;
@@ -1171,44 +1158,7 @@
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,
@@ -1437,35 +1387,6 @@
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/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 @@
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_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/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 @@
\
} 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/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 @@
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 @@
}
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 @@
fprintf(stderr, "Error %d parsing input device configuration file.\n\n", status);
return false;
}
+ delete map;
break;
}
@@ -114,6 +115,7 @@
fprintf(stderr, "Error %d parsing virtual key definition file.\n\n", status);
return false;
}
+ delete map;
break;
}
}