summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/Activity.java6
-rw-r--r--core/java/android/content/ContentProviderNative.java19
-rw-r--r--core/java/android/provider/Settings.java7
-rw-r--r--core/java/android/text/TextLine.java21
-rw-r--r--core/java/android/view/ViewRoot.java4
-rw-r--r--core/res/res/values-in-rID/arrays.xml (renamed from core/res/res/values-id-rID/arrays.xml)0
-rw-r--r--core/res/res/values-in-rID/donottranslate-cldr.xml (renamed from core/res/res/values-id-rID/donottranslate-cldr.xml)0
-rw-r--r--core/res/res/values-in/donottranslate-cldr.xml (renamed from core/res/res/values-id/donottranslate-cldr.xml)0
-rw-r--r--core/res/res/values-in/strings.xml (renamed from core/res/res/values-id/strings.xml)0
-rw-r--r--core/res/res/values-iw-rIL/arrays.xml (renamed from core/res/res/values-he-rIL/arrays.xml)0
-rw-r--r--core/res/res/values-iw/donottranslate-cldr.xml (renamed from core/res/res/values-he/donottranslate-cldr.xml)0
-rw-r--r--core/res/res/values-iw/strings.xml (renamed from core/res/res/values-he/strings.xml)0
-rwxr-xr-xcore/res/res/values/strings.xml2
-rwxr-xr-xcore/tests/ConnectivityManagerTest/assets/accesspoints.xml12
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java148
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java197
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java97
-rw-r--r--data/keyboards/Vendor_046d_Product_c532.kl (renamed from data/keyboards/Logitech_USB_Receiver.kl)2
-rw-r--r--data/keyboards/Vendor_05ac_Product_0239.kl (renamed from data/keyboards/Apple_Wireless_Keyboard.kl)0
-rw-r--r--data/keyboards/Vendor_22b8_Product_093d.kl (renamed from data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl)0
-rw-r--r--data/keyboards/common.mk18
-rw-r--r--data/keyboards/keyboards.mk6
-rw-r--r--data/keyboards/qwerty.idc23
-rw-r--r--data/keyboards/qwerty2.idc23
-rw-r--r--data/keyboards/qwerty2.kl109
-rw-r--r--graphics/java/android/graphics/Paint.java1
-rw-r--r--include/ui/EventHub.h120
-rw-r--r--include/ui/Input.h38
-rw-r--r--include/ui/InputReader.h15
-rw-r--r--include/ui/Keyboard.h48
-rw-r--r--include/ui/VirtualKeyMap.h79
-rw-r--r--include/utils/String8.h11
-rw-r--r--include/utils/Tokenizer.h4
-rw-r--r--libs/ui/Android.mk1
-rw-r--r--libs/ui/EventHub.cpp585
-rw-r--r--libs/ui/Input.cpp39
-rw-r--r--libs/ui/InputDispatcher.cpp10
-rw-r--r--libs/ui/InputReader.cpp18
-rw-r--r--libs/ui/Keyboard.cpp183
-rw-r--r--libs/ui/VirtualKeyMap.cpp171
-rw-r--r--libs/ui/tests/InputReader_test.cpp38
-rw-r--r--libs/utils/FileMap.cpp8
-rw-r--r--libs/utils/String8.cpp18
-rw-r--r--libs/utils/Tokenizer.cpp45
-rw-r--r--media/java/android/media/MediaFile.java1
-rwxr-xr-xmedia/java/android/media/videoeditor/VideoEditor.java30
-rwxr-xr-xmedia/java/android/media/videoeditor/VideoEditorFactory.java53
-rw-r--r--media/java/android/media/videoeditor/VideoEditorImpl.java (renamed from media/java/android/media/videoeditor/VideoEditorTestImpl.java)14
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp12
-rw-r--r--media/libstagefright/AwesomePlayer.cpp3
-rw-r--r--media/libstagefright/codecs/avc/enc/AVCEncoder.cpp2
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp2
-rw-r--r--media/libstagefright/httplive/LiveSource.cpp8
-rw-r--r--media/libstagefright/httplive/M3UParser.cpp22
-rw-r--r--media/libstagefright/include/M3UParser.h2
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp12
-rw-r--r--media/libstagefright/mpeg2ts/ESQueue.cpp47
-rw-r--r--packages/DefaultContainerService/res/values-in/strings.xml (renamed from packages/DefaultContainerService/res/values-id/strings.xml)0
-rw-r--r--packages/DefaultContainerService/res/values-iw/strings.xml (renamed from packages/DefaultContainerService/res/values-he/strings.xml)0
-rw-r--r--packages/SettingsProvider/res/values-in/strings.xml (renamed from packages/SettingsProvider/res/values-id/strings.xml)0
-rw-r--r--packages/SettingsProvider/res/values-iw/strings.xml (renamed from packages/SettingsProvider/res/values-he/strings.xml)0
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.pngbin1108 -> 1072 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.pngbin738 -> 897 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.pngbin1630 -> 2692 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.pngbin2223 -> 2920 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.pngbin958 -> 1076 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.pngbin1787 -> 2673 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.pngbin456 -> 370 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.pngbin1306 -> 1524 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.pngbin416 -> 407 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.pngbin1114 -> 1912 bytes
-rw-r--r--packages/SystemUI/res/values-in/strings.xml (renamed from packages/SystemUI/res/values-id/strings.xml)0
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml (renamed from packages/SystemUI/res/values-he/strings.xml)0
-rw-r--r--packages/VpnServices/res/values-in/strings.xml (renamed from packages/VpnServices/res/values-id/strings.xml)0
-rw-r--r--packages/VpnServices/res/values-iw/strings.xml (renamed from packages/VpnServices/res/values-he/strings.xml)0
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java2
-rw-r--r--services/java/com/android/server/ConnectivityService.java18
-rw-r--r--services/java/com/android/server/InputManager.java58
-rw-r--r--services/java/com/android/server/SamplingProfilerService.java11
-rw-r--r--services/java/com/android/server/WindowManagerService.java3
-rw-r--r--services/jni/com_android_server_InputManager.cpp72
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java26
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java36
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java47
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java18
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java218
-rw-r--r--tools/validatekeymaps/Main.cpp25
87 files changed, 1727 insertions, 1141 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0a2e031..a0a6b42 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2363,7 +2363,11 @@ public class Activity extends ContextThemeWrapper
*/
public boolean onMenuOpened(int featureId, Menu menu) {
if (featureId == Window.FEATURE_ACTION_BAR) {
- mActionBar.dispatchMenuVisibilityChanged(true);
+ if (mActionBar != null) {
+ mActionBar.dispatchMenuVisibilityChanged(true);
+ } else {
+ Log.e(TAG, "Tried to open action bar menu with no action bar");
+ }
}
return true;
}
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index d1ab8d5..abeeb74 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -110,16 +110,23 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
IBulkCursor bulkCursor = bulkQuery(url, projection, selection,
selectionArgs, sortOrder, observer, window);
- reply.writeNoException();
if (bulkCursor != null) {
- reply.writeStrongBinder(bulkCursor.asBinder());
-
+ final IBinder binder = bulkCursor.asBinder();
if (wantsCursorMetadata) {
- reply.writeInt(bulkCursor.count());
- reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex(
- bulkCursor.getColumnNames()));
+ final int count = bulkCursor.count();
+ final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex(
+ bulkCursor.getColumnNames());
+
+ reply.writeNoException();
+ reply.writeStrongBinder(binder);
+ reply.writeInt(count);
+ reply.writeInt(index);
+ } else {
+ reply.writeNoException();
+ reply.writeStrongBinder(binder);
}
} else {
+ reply.writeNoException();
reply.writeStrongBinder(null);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4ea4a16..ed71da2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2576,12 +2576,13 @@ public final class Settings {
public static final String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
/**
- * A positive value indicates the frequency of SamplingProfiler
- * taking snapshots in hertz. Zero value means SamplingProfiler is disabled.
+ * A positive value indicates how often the SamplingProfiler
+ * should take snapshots. Zero value means SamplingProfiler
+ * is disabled.
*
* @hide
*/
- public static final String SAMPLING_PROFILER_HZ = "sampling_profiler_hz";
+ public static final String SAMPLING_PROFILER_MS = "sampling_profiler_ms";
/**
* Settings classname to launch when Settings is clicked from All
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 2f7482c..a6fd2f1 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -663,6 +663,25 @@ class TextLine {
}
/**
+ * @param wp
+ */
+ private static void expandMetricsFromPaint(FontMetricsInt fmi, TextPaint wp) {
+ final int previousTop = fmi.top;
+ final int previousAscent = fmi.ascent;
+ final int previousDescent = fmi.descent;
+ final int previousBottom = fmi.bottom;
+ final int previousLeading = fmi.leading;
+
+ wp.getFontMetricsInt(fmi);
+
+ fmi.top = Math.min(fmi.top, previousTop);
+ fmi.ascent = Math.min(fmi.ascent, previousAscent);
+ fmi.descent = Math.max(fmi.descent, previousDescent);
+ fmi.bottom = Math.max(fmi.bottom, previousBottom);
+ fmi.leading = Math.max(fmi.leading, previousLeading);
+ }
+
+ /**
* Utility function for measuring and rendering text. The text must
* not include a tab or emoji.
*
@@ -703,7 +722,7 @@ class TextLine {
}
if (fmi != null) {
- wp.getFontMetricsInt(fmi);
+ expandMetricsFromPaint(fmi, wp);
}
if (c != null) {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 5f3184d..dcde6ef 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2611,6 +2611,10 @@ public final class ViewRoot extends Handler implements ViewParent,
captureKeyLog("captureDispatchKeyEvent", event);
}
+ // Make sure the fallback event policy sees all keys that will be delivered to the
+ // view hierarchy.
+ mFallbackEventHandler.preDispatchKeyEvent(event);
+
// Deliver the key to the view hierarchy.
if (mView.dispatchKeyEvent(event)) {
finishKeyEvent(event, sendDone, true);
diff --git a/core/res/res/values-id-rID/arrays.xml b/core/res/res/values-in-rID/arrays.xml
index 512cace..512cace 100644
--- a/core/res/res/values-id-rID/arrays.xml
+++ b/core/res/res/values-in-rID/arrays.xml
diff --git a/core/res/res/values-id-rID/donottranslate-cldr.xml b/core/res/res/values-in-rID/donottranslate-cldr.xml
index 4d4ebb2..4d4ebb2 100644
--- a/core/res/res/values-id-rID/donottranslate-cldr.xml
+++ b/core/res/res/values-in-rID/donottranslate-cldr.xml
diff --git a/core/res/res/values-id/donottranslate-cldr.xml b/core/res/res/values-in/donottranslate-cldr.xml
index 7a58a19..7a58a19 100644
--- a/core/res/res/values-id/donottranslate-cldr.xml
+++ b/core/res/res/values-in/donottranslate-cldr.xml
diff --git a/core/res/res/values-id/strings.xml b/core/res/res/values-in/strings.xml
index aa243e0..aa243e0 100644
--- a/core/res/res/values-id/strings.xml
+++ b/core/res/res/values-in/strings.xml
diff --git a/core/res/res/values-he-rIL/arrays.xml b/core/res/res/values-iw-rIL/arrays.xml
index 87c1231..87c1231 100644
--- a/core/res/res/values-he-rIL/arrays.xml
+++ b/core/res/res/values-iw-rIL/arrays.xml
diff --git a/core/res/res/values-he/donottranslate-cldr.xml b/core/res/res/values-iw/donottranslate-cldr.xml
index d373a34..d373a34 100644
--- a/core/res/res/values-he/donottranslate-cldr.xml
+++ b/core/res/res/values-iw/donottranslate-cldr.xml
diff --git a/core/res/res/values-he/strings.xml b/core/res/res/values-iw/strings.xml
index 25074ea..25074ea 100644
--- a/core/res/res/values-he/strings.xml
+++ b/core/res/res/values-iw/strings.xml
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index eafa9b6..0f5ff05 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1806,7 +1806,7 @@
<!-- Do not translate. WebView User Agent string -->
<string name="web_user_agent" translatable="false">Mozilla/5.0 (Linux; U; <xliff:g id="x">Android %s</xliff:g>)
- AppleWebKit/534.12 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.12</string>
+ AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.13</string>
<!-- Do not translate. WebView User Agent targeted content -->
<string name="web_user_agent_target_content" translatable="false">"Mobile "</string>
diff --git a/core/tests/ConnectivityManagerTest/assets/accesspoints.xml b/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
index 2b0e4af..5e3252c 100755
--- a/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
+++ b/core/tests/ConnectivityManagerTest/assets/accesspoints.xml
@@ -4,7 +4,7 @@
<ssid>opennet</ssid>
<security>NONE</security>
</accesspoint>
- <accesspoint>
+ <accesspoint>
<ssid>GoogleGuest</ssid>
<security>NONE</security>
</accesspoint>
@@ -14,6 +14,16 @@
<password>androidwifi</password>
</accesspoint>
<accesspoint>
+ <ssid>securenetstatic</ssid>
+ <security>PSK</security>
+ <password>androidwifi</password>
+ <ip>192.168.14.2</ip>
+ <gateway>192.168.14.1</gateway>
+ <networkprefixlength>24</networkprefixlength>
+ <dns1>192.168.14.1</dns1>
+ <dns2>192.168.1.9</dns2>
+ </accesspoint>
+ <accesspoint>
<ssid>botnet</ssid>
<security>EAP</security>
<eap>PEAP</eap>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index 863fbe6..21f1bfc 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -25,11 +25,18 @@ import org.xml.sax.helpers.DefaultHandler;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
-
+import android.net.wifi.WifiConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.util.Log;
+
import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
@@ -38,7 +45,8 @@ import java.util.List;
* The configurations of an access point is included in tag
* <accesspoint></accesspoint>. The supported configuration includes: ssid,
* security, eap, phase2, identity, password, anonymousidentity, cacert, usercert,
- * in which each is included in the corresponding tags. All access points have to be
+ * in which each is included in the corresponding tags. Static IP setting is also supported.
+ * Tags that can be used include: ip, gateway, netmask, dns1, dns2. All access points have to be
* enclosed in tags of <resources></resources>.
*
* The following is a sample configuration file for an access point using EAP-PEAP with MSCHAP2.
@@ -52,6 +60,9 @@ import java.util.List;
* <password>abcdefgh</password>
* </accesspoint>
* </resources>
+ *
+ * Note:ssid and security have to be the first two tags
+ * for static ip setting, tag "ip" should be listed before other fields: dns, gateway, netmask.
*/
public class AccessPointParserHelper {
private static final String KEYSTORE_SPACE = "keystore://";
@@ -93,9 +104,11 @@ public class AccessPointParserHelper {
boolean security = false;
boolean password = false;
boolean ip = false;
- boolean subnetmask = false;
boolean gateway = false;
- boolean dns = false;
+ boolean networkprefix = false;
+ boolean netmask = false;
+ boolean dns1 = false;
+ boolean dns2 = false;
boolean eap = false;
boolean phase2 = false;
boolean identity = false;
@@ -104,6 +117,8 @@ public class AccessPointParserHelper {
boolean usercert = false;
WifiConfiguration config = null;
int securityType = NONE;
+ LinkProperties mLinkProperties = null;
+ InetAddress mInetAddr = null;
@Override
public void startElement(String uri, String localName, String tagName,
@@ -138,12 +153,37 @@ public class AccessPointParserHelper {
if (tagName.equalsIgnoreCase("usercert")) {
usercert = true;
}
+ if (tagName.equalsIgnoreCase("ip")) {
+ mLinkProperties = new LinkProperties();
+ ip = true;
+ }
+ if (tagName.equalsIgnoreCase("gateway")) {
+ gateway = true;
+ }
+ if (tagName.equalsIgnoreCase("networkprefixlength")) {
+ networkprefix = true;
+ }
+ if (tagName.equalsIgnoreCase("netmask")) {
+ netmask = true;
+ }
+ if (tagName.equalsIgnoreCase("dns1")) {
+ dns1 = true;
+ }
+ if (tagName.equalsIgnoreCase("dns2")) {
+ dns2 = true;
+ }
}
@Override
public void endElement(String uri, String localName, String tagName) throws SAXException {
- Log.v(TAG, "endElement: " + tagName);
if (tagName.equalsIgnoreCase("accesspoint")) {
+ if (mLinkProperties != null) {
+ config.ipAssignment = IpAssignment.STATIC;
+ config.linkProperties = mLinkProperties;
+ } else {
+ config.ipAssignment = IpAssignment.DHCP;
+ }
+ config.proxySettings = ProxySettings.NONE;
networks.add(config);
}
}
@@ -152,14 +192,11 @@ public class AccessPointParserHelper {
public void characters(char ch[], int start, int length) throws SAXException {
if (ssid) {
config.SSID = new String(ch, start, length);
- Log.v(TAG, "ssid: " + config.SSID);
ssid = false;
}
if (security) {
String securityStr = (new String(ch, start, length)).toUpperCase();
- Log.v(TAG, "security: " + securityStr);
securityType = getSecurityType(securityStr);
- Log.v(TAG, "securityType = " + securityType);
switch (securityType) {
case NONE:
config.allowedKeyManagement.set(KeyMgmt.NONE);
@@ -175,6 +212,13 @@ public class AccessPointParserHelper {
case EAP:
config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ // Initialize other fields.
+ config.phase2.setValue("");
+ config.ca_cert.setValue("");
+ config.client_cert.setValue("");
+ config.private_key.setValue("");
+ config.identity.setValue("");
+ config.anonymous_identity.setValue("");
break;
default:
throw new SAXException();
@@ -187,7 +231,6 @@ public class AccessPointParserHelper {
if (len == 0) {
throw new SAXException();
}
- Log.v(TAG, "passwordStr:" + passwordStr);
if (securityType == WEP) {
if ((len == 10 || len == 26 || len == 58) &&
passwordStr.matches("[0-9A-Fa-f]*")) {
@@ -242,21 +285,94 @@ public class AccessPointParserHelper {
config.client_cert.setValue(KEYSTORE_SPACE);
usercert = false;
}
+ if (ip) {
+ try {
+ String ipAddr = new String(ch, start, length);
+ if (!InetAddress.isNumeric(ipAddr)) {
+ throw new SAXException();
+ }
+ mInetAddr = InetAddress.getByName(ipAddr);
+ } catch (UnknownHostException e) {
+ throw new SAXException();
+ }
+ ip = false;
+ }
+ if (gateway) {
+ try {
+ String gwAddr = new String(ch, start, length);
+ if (!InetAddress.isNumeric(gwAddr)) {
+ throw new SAXException();
+ }
+ mLinkProperties.setGateway(InetAddress.getByName(gwAddr));
+ } catch (UnknownHostException e) {
+ throw new SAXException();
+ }
+ gateway = false;
+ }
+ if (networkprefix) {
+ try {
+ int nwPrefixLength = Integer.parseInt(new String(ch, start, length));
+ if ((nwPrefixLength < 0) || (nwPrefixLength > 32)) {
+ throw new SAXException();
+ }
+ mLinkProperties.addLinkAddress(new LinkAddress(mInetAddr, nwPrefixLength));
+ } catch (NumberFormatException e) {
+ throw new SAXException();
+ }
+ networkprefix = false;
+ }
+ if (netmask) {
+ try {
+ String netMaskStr = new String(ch, start, length);
+ if (!InetAddress.isNumeric(netMaskStr)) {
+ throw new SAXException();
+ }
+ InetAddress netMaskAddr = InetAddress.getByName(netMaskStr);
+ mLinkProperties.addLinkAddress(new LinkAddress(mInetAddr, netMaskAddr));
+ } catch (UnknownHostException e) {
+ throw new SAXException();
+ }
+ netmask = false;
+ }
+ if (dns1) {
+ try {
+ String dnsAddr = new String(ch, start, length);
+ if (!InetAddress.isNumeric(dnsAddr)) {
+ throw new SAXException();
+ }
+ mLinkProperties.addDns(InetAddress.getByName(dnsAddr));
+ } catch (UnknownHostException e) {
+ throw new SAXException();
+ }
+ dns1 = false;
+ }
+ if (dns2) {
+ try {
+ String dnsAddr = new String(ch, start, length);
+ if (!InetAddress.isNumeric(dnsAddr)) {
+ throw new SAXException();
+ }
+ mLinkProperties.addDns(InetAddress.getByName(dnsAddr));
+ } catch (UnknownHostException e) {
+ throw new SAXException();
+ }
+ dns2 = false;
+ }
}
};
- public AccessPointParserHelper() {
- }
-
/**
- * Process the accesspoint.xml file
- * @return List of WifiConfiguration
- * @throws Exception when parsing the XML file
+ * Process the InputStream in
+ * @param in is the InputStream that can be used for XML parsing
+ * @throws Exception
*/
- public List<WifiConfiguration> processAccessPoint(InputStream in) throws Exception {
+ public AccessPointParserHelper(InputStream in) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
saxParser.parse(in, mHandler);
+ }
+
+ public List<WifiConfiguration> getNetworkConfigurations() throws Exception {
return networks;
}
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 37b9f52..2888696 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -16,10 +16,8 @@
package com.android.connectivitymanagertest;
-import com.android.connectivitymanagertest.R;
import android.app.Activity;
import android.content.Context;
-import android.content.res.Resources;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
@@ -36,7 +34,6 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
-import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiInfo;
@@ -52,7 +49,7 @@ public class ConnectivityManagerTestActivity extends Activity {
public static final String LOG_TAG = "ConnectivityManagerTestActivity";
public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
- public static final int WIFI_SCAN_TIMEOUT = 20 * 1000;
+ public static final int WIFI_SCAN_TIMEOUT = 50 * 1000;
public static final int SHORT_TIMEOUT = 5 * 1000;
public static final long LONG_TIMEOUT = 50 * 1000;
public static final int SUCCESS = 0; // for Wifi tethering state change
@@ -61,6 +58,7 @@ public class ConnectivityManagerTestActivity extends Activity {
private static final String ACCESS_POINT_FILE = "accesspoints.xml";
public ConnectivityReceiver mConnectivityReceiver = null;
public WifiReceiver mWifiReceiver = null;
+ private AccessPointParserHelper mParseHelper = null;
/*
* Track network connectivity information
*/
@@ -101,7 +99,7 @@ public class ConnectivityManagerTestActivity extends Activity {
private class ConnectivityReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent);
+ log("ConnectivityReceiver: onReceive() is called with " + intent);
String action = intent.getAction();
if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
@@ -126,9 +124,9 @@ public class ConnectivityManagerTestActivity extends Activity {
mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
mIsFailOver = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
- Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString());
+ log("mNetworkInfo: " + mNetworkInfo.toString());
if (mOtherNetworkInfo != null) {
- Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
+ log("mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
}
recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
if (mOtherNetworkInfo != null) {
@@ -148,7 +146,7 @@ public class ConnectivityManagerTestActivity extends Activity {
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mWifiNetworkInfo =
(NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
+ log("mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
if (mWifiNetworkInfo.getState() == State.CONNECTED) {
mBssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
}
@@ -181,7 +179,7 @@ public class ConnectivityManagerTestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Log.v(LOG_TAG, "onCreate, inst=" + Integer.toHexString(hashCode()));
+ log("onCreate, inst=" + Integer.toHexString(hashCode()));
// Create a simple layout
LinearLayout contentView = new LinearLayout(this);
@@ -212,7 +210,7 @@ public class ConnectivityManagerTestActivity extends Activity {
initializeNetworkStates();
if (mWifiManager.isWifiEnabled()) {
- Log.v(LOG_TAG, "Clear Wifi before we start the test.");
+ log("Clear Wifi before we start the test.");
removeConfiguredNetworksAndDisableWifi();
}
mWifiRegexs = mCM.getTetherableWifiRegexs();
@@ -220,32 +218,22 @@ public class ConnectivityManagerTestActivity extends Activity {
public List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
InputStream in = getAssets().open(ACCESS_POINT_FILE);
- AccessPointParserHelper parseHelper = new AccessPointParserHelper();
- return parseHelper.processAccessPoint(in);
- }
-
- private void printNetConfig(String[] configuration) {
- for (int i = 0; i < configuration.length; i++) {
- if (i == 0) {
- Log.v(LOG_TAG, "SSID: " + configuration[0]);
- } else {
- Log.v(LOG_TAG, " " + configuration[i]);
- }
- }
+ mParseHelper = new AccessPointParserHelper(in);
+ return mParseHelper.getNetworkConfigurations();
}
// for each network type, initialize network states to UNKNOWN, and no verification flag is set
public void initializeNetworkStates() {
for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
connectivityState[networkType] = new NetworkState();
- Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " +
+ log("Initialize network state for " + networkType + ": " +
connectivityState[networkType].toString());
}
}
// deposit a network state
public void recordNetworkState(int networkType, State networkState) {
- Log.v(LOG_TAG, "record network state for network " + networkType +
+ log("record network state for network " + networkType +
", state is " + networkState);
connectivityState[networkType].recordState(networkState);
}
@@ -259,40 +247,40 @@ public class ConnectivityManagerTestActivity extends Activity {
// Validate the states recorded
public boolean validateNetworkStates(int networkType) {
- Log.v(LOG_TAG, "validate network state for " + networkType + ": ");
+ log("validate network state for " + networkType + ": ");
return connectivityState[networkType].validateStateTransition();
}
// return result from network state validation
public String getTransitionFailureReason(int networkType) {
- Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " +
+ log("get network state transition failure reason for " + networkType + ": " +
connectivityState[networkType].toString());
return connectivityState[networkType].getReason();
}
private void notifyNetworkConnectivityChange() {
synchronized(connectivityObject) {
- Log.v(LOG_TAG, "notify network connectivity changed");
+ log("notify network connectivity changed");
connectivityObject.notifyAll();
}
}
private void notifyScanResult() {
synchronized (this) {
- Log.v(LOG_TAG, "notify that scan results are available");
+ log("notify that scan results are available");
this.notify();
}
}
private void notifyWifiState() {
synchronized (wifiObject) {
- Log.v(LOG_TAG, "notify wifi state changed");
+ log("notify wifi state changed");
wifiObject.notify();
}
}
private void notifyWifiAPState() {
synchronized (this) {
- Log.v(LOG_TAG, "notify wifi AP state changed");
+ log("notify wifi AP state changed");
this.notify();
}
}
@@ -306,7 +294,7 @@ public class ConnectivityManagerTestActivity extends Activity {
for (Object obj: tethered) {
String str = (String)obj;
for (String tethRex: mWifiRegexs) {
- Log.v(LOG_TAG, "str: " + str +"tethRex: " + tethRex);
+ log("str: " + str +"tethRex: " + tethRex);
if (str.matches(tethRex)) {
wifiTethered = true;
}
@@ -316,7 +304,7 @@ public class ConnectivityManagerTestActivity extends Activity {
for (Object obj: errored) {
String str = (String)obj;
for (String tethRex: mWifiRegexs) {
- Log.v(LOG_TAG, "error: str: " + str +"tethRex: " + tethRex);
+ log("error: str: " + str +"tethRex: " + tethRex);
if (str.matches(tethRex)) {
wifiErrored = true;
}
@@ -328,7 +316,7 @@ public class ConnectivityManagerTestActivity extends Activity {
} else if (wifiErrored) {
mWifiTetherResult = FAILURE; // wifi tethering failed
}
- Log.v(LOG_TAG, "mWifiTetherResult: " + mWifiTetherResult);
+ log("mWifiTetherResult: " + mWifiTetherResult);
this.notify();
}
}
@@ -344,12 +332,12 @@ public class ConnectivityManagerTestActivity extends Activity {
return false;
} else {
// the broadcast has been sent out. the state has been changed.
- Log.v(LOG_TAG, "networktype: " + networkType + " state: " +
+ log("networktype: " + networkType + " state: " +
mCM.getNetworkInfo(networkType));
return true;
}
}
- Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
+ log("Wait for the connectivity state for network: " + networkType +
" to be " + expectedState.toString());
synchronized (connectivityObject) {
try {
@@ -359,7 +347,7 @@ public class ConnectivityManagerTestActivity extends Activity {
}
if ((mNetworkInfo.getType() != networkType) ||
(mNetworkInfo.getState() != expectedState)) {
- Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() +
+ log("network state for " + mNetworkInfo.getType() +
"is: " + mNetworkInfo.getState());
continue;
}
@@ -380,7 +368,7 @@ public class ConnectivityManagerTestActivity extends Activity {
return true;
}
}
- Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
+ log("Wait for wifi state to be: " + expectedState);
synchronized (wifiObject) {
try {
wifiObject.wait(SHORT_TIMEOUT);
@@ -388,7 +376,7 @@ public class ConnectivityManagerTestActivity extends Activity {
e.printStackTrace();
}
if (mWifiState != expectedState) {
- Log.v(LOG_TAG, "Wifi state is: " + mWifiNetworkInfo.getState());
+ log("Wifi state is: " + mWifiState);
continue;
}
return true;
@@ -408,7 +396,7 @@ public class ConnectivityManagerTestActivity extends Activity {
return true;
}
}
- Log.v(LOG_TAG, "Wait for wifi AP state to be: " + expectedState);
+ log("Wait for wifi AP state to be: " + expectedState);
synchronized (wifiObject) {
try {
wifiObject.wait(SHORT_TIMEOUT);
@@ -416,7 +404,7 @@ public class ConnectivityManagerTestActivity extends Activity {
e.printStackTrace();
}
if (mWifiManager.getWifiApState() != expectedState) {
- Log.v(LOG_TAG, "Wifi state is: " + mWifiManager.getWifiApState());
+ log("Wifi state is: " + mWifiManager.getWifiApState());
continue;
}
return true;
@@ -436,7 +424,7 @@ public class ConnectivityManagerTestActivity extends Activity {
if ((System.currentTimeMillis() - startTime) > timeout) {
return mWifiTetherResult;
}
- Log.v(LOG_TAG, "Wait for wifi tethering result.");
+ log("Wait for wifi tethering result.");
synchronized (this) {
try {
this.wait(SHORT_TIMEOUT);
@@ -490,64 +478,61 @@ public class ConnectivityManagerTestActivity extends Activity {
//If Wifi is not enabled, enable it
if (!mWifiManager.isWifiEnabled()) {
- Log.v(LOG_TAG, "Wifi is not enabled, enable it");
+ log("Wifi is not enabled, enable it");
mWifiManager.setWifiEnabled(true);
+ // wait for the wifi state change before start scanning.
+ if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, 2*SHORT_TIMEOUT)) {
+ log("wait for WIFI_STATE_ENABLED failed");
+ return false;
+ }
}
- List<ScanResult> netList = mWifiManager.getScanResults();
- if (netList == null) {
- Log.v(LOG_TAG, "scan results are null");
- // if no scan results are available, start active scan
- mWifiManager.startScanActive();
- mScanResultIsAvailable = false;
- long startTime = System.currentTimeMillis();
- while (!mScanResultIsAvailable) {
- if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
- return false;
+ boolean foundApInScanResults = false;
+ for (int retry = 0; retry < 5; retry++) {
+ List<ScanResult> netList = mWifiManager.getScanResults();
+ if (netList != null) {
+ log("size of scan result list: " + netList.size());
+ for (int i = 0; i < netList.size(); i++) {
+ ScanResult sr= netList.get(i);
+ if (sr.SSID.equals(ssid)) {
+ log("found " + ssid + " in the scan result list");
+ log("retry: " + retry);
+ foundApInScanResults = true;
+ mWifiManager.connectNetwork(config);
+ break;
+ }
}
- // wait for the scan results to be available
- synchronized (this) {
- // wait for the scan result to be available
- try {
- this.wait(WAIT_FOR_SCAN_RESULT);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ }
+ if (foundApInScanResults) {
+ return true;
+ } else {
+ // Start an active scan
+ mWifiManager.startScanActive();
+ mScanResultIsAvailable = false;
+ long startTime = System.currentTimeMillis();
+ while (!mScanResultIsAvailable) {
+ if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
+ log("wait for scan results timeout");
+ return false;
}
- if ((mWifiManager.getScanResults() == null) ||
- (mWifiManager.getScanResults().size() <= 0)) {
- continue;
+ // wait for the scan results to be available
+ synchronized (this) {
+ // wait for the scan result to be available
+ try {
+ this.wait(WAIT_FOR_SCAN_RESULT);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if ((mWifiManager.getScanResults() == null) ||
+ (mWifiManager.getScanResults().size() <= 0)) {
+ continue;
+ }
+ mScanResultIsAvailable = true;
}
- mScanResultIsAvailable = true;
}
}
}
-
- netList = mWifiManager.getScanResults();
-
- for (int i = 0; i < netList.size(); i++) {
- ScanResult sr= netList.get(i);
- if (sr.SSID.equals(ssid)) {
- Log.v(LOG_TAG, "found " + ssid + " in the scan result list");
- int networkId = mWifiManager.addNetwork(config);
- // Connect to network by disabling others.
- mWifiManager.enableNetwork(networkId, true);
- mWifiManager.saveConfiguration();
- List<WifiConfiguration> wifiNetworks = mWifiManager.getConfiguredNetworks();
- for (WifiConfiguration netConfig : wifiNetworks) {
- Log.v(LOG_TAG, netConfig.toString());
- }
-
- mWifiManager.reconnect();
- break;
- }
- }
-
- List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
- if (netConfList.size() <= 0) {
- Log.v(LOG_TAG, ssid + " is not available");
- return false;
- }
- return true;
+ return false;
}
/*
@@ -555,27 +540,13 @@ public class ConnectivityManagerTestActivity extends Activity {
*/
public boolean disconnectAP() {
if (mWifiManager.isWifiEnabled()) {
- //remove the current network Id
- WifiInfo curWifi = mWifiManager.getConnectionInfo();
- if (curWifi == null) {
- return false;
- }
- int curNetworkId = curWifi.getNetworkId();
- mWifiManager.removeNetwork(curNetworkId);
- mWifiManager.saveConfiguration();
-
- // remove other saved networks
- List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
- if (netConfList != null) {
- Log.v(LOG_TAG, "remove configured network ids");
- for (int i = 0; i < netConfList.size(); i++) {
- WifiConfiguration conf = new WifiConfiguration();
- conf = netConfList.get(i);
- mWifiManager.removeNetwork(conf.networkId);
- }
+ // remove saved networks
+ List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
+ for (WifiConfiguration wifiConfig: wifiConfigList) {
+ log("remove wifi configuration: " + wifiConfig.toString());
+ mWifiManager.forgetNetwork(wifiConfig.networkId);
}
}
- mWifiManager.saveConfiguration();
return true;
}
/**
@@ -599,7 +570,7 @@ public class ConnectivityManagerTestActivity extends Activity {
}
// Wait for the actions to be completed
try {
- Thread.sleep(5*1000);
+ Thread.sleep(SHORT_TIMEOUT);
} catch (InterruptedException e) {}
return true;
}
@@ -632,7 +603,7 @@ public class ConnectivityManagerTestActivity extends Activity {
if (mWifiReceiver != null) {
unregisterReceiver(mWifiReceiver);
}
- Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
+ log("onDestroy, inst=" + Integer.toHexString(hashCode()));
}
@Override
@@ -674,4 +645,8 @@ public class ConnectivityManagerTestActivity extends Activity {
}
return super.onKeyDown(keyCode, event);
}
+
+ private void log(String message) {
+ Log.v(LOG_TAG, message);
+ }
}
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index 69eb5db..9c72102 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -17,26 +17,33 @@
package com.android.connectivitymanagertest.functional;
import com.android.connectivitymanagertest.ConnectivityManagerTestActivity;
-import com.android.connectivitymanagertest.NetworkState;
+import com.android.connectivitymanagertest.ConnectivityManagerTestRunner;
import android.R;
import android.app.Activity;
+import android.content.ContentResolver;
import android.content.Intent;
import android.content.Context;
import android.content.res.Resources;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiConfiguration.Status;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.ConnectivityManager;
+import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
+import android.provider.Settings;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Test Wi-Fi connection with different configuration
@@ -48,18 +55,25 @@ import java.util.List;
public class WifiConnectionTest
extends ActivityInstrumentationTestCase2<ConnectivityManagerTestActivity> {
private static final String TAG = "WifiConnectionTest";
- private static final boolean DEBUG = true;
- private static final String PKG_NAME = "com.android.connectivitymanagertests";
+ private static final boolean DEBUG = false;
private List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
private ConnectivityManagerTestActivity mAct;
+ private ConnectivityManagerTestRunner mRunner;
+ private WifiManager mWifiManager = null;
+ private Set<WifiConfiguration> enabledNetworks = null;
public WifiConnectionTest() {
- super(PKG_NAME, ConnectivityManagerTestActivity.class);
+ super(ConnectivityManagerTestActivity.class);
}
@Override
public void setUp() throws Exception {
super.setUp();
+ log("before we launch the test activity, we preserve all the configured networks.");
+ mRunner = ((ConnectivityManagerTestRunner)getInstrumentation());
+ mWifiManager = (WifiManager) mRunner.getContext().getSystemService(Context.WIFI_SERVICE);
+ enabledNetworks = getEnabledNetworks(mWifiManager.getConfiguredNetworks());
+
mAct = getActivity();
networks = mAct.loadNetworkConfigurations();
if (DEBUG) {
@@ -68,30 +82,61 @@ public class WifiConnectionTest
// enable Wifi and verify wpa_supplicant is started
assertTrue("enable Wifi failed", mAct.enableWifi());
- try {
- Thread.sleep( 2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT);
- } catch (Exception e) {
- fail("interrupted while waiting for WPA_SUPPLICANT to start");
- }
+ sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT,
+ "interrupted while waiting for WPA_SUPPLICANT to start");
WifiInfo mConnection = mAct.mWifiManager.getConnectionInfo();
assertNotNull(mConnection);
assertTrue("wpa_supplicant is not started ", mAct.mWifiManager.pingSupplicant());
}
private void printNetworkConfigurations() {
- Log.v(TAG, "==== print network configurations parsed from XML file ====");
- Log.v(TAG, "number of access points: " + networks.size());
+ log("==== print network configurations parsed from XML file ====");
+ log("number of access points: " + networks.size());
for (WifiConfiguration config : networks) {
- Log.v(TAG, config.toString());
+ log(config.toString());
}
}
@Override
public void tearDown() throws Exception {
+ log("tearDown()");
mAct.removeConfiguredNetworksAndDisableWifi();
+ reEnableNetworks(enabledNetworks);
super.tearDown();
}
+ private Set<WifiConfiguration> getEnabledNetworks(List<WifiConfiguration> configuredNetworks) {
+ Set<WifiConfiguration> networks = new HashSet<WifiConfiguration>();
+ for (WifiConfiguration wifiConfig : configuredNetworks) {
+ if (wifiConfig.status == Status.ENABLED || wifiConfig.status == Status.CURRENT) {
+ networks.add(wifiConfig);
+ log("remembering enabled network " + wifiConfig.SSID +
+ " status is " + wifiConfig.status);
+ }
+ }
+ return networks;
+ }
+
+ private void reEnableNetworks(Set<WifiConfiguration> enabledNetworks) {
+ if (!mWifiManager.isWifiEnabled()) {
+ log("reEnableNetworks: enable Wifi");
+ mWifiManager.setWifiEnabled(true);
+ sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT,
+ "interruped while waiting for wifi to be enabled");
+ }
+
+ for (WifiConfiguration config : enabledNetworks) {
+ if (DEBUG) {
+ log("recover wifi configuration: " + config.toString());
+ }
+ config.SSID = "\"" + config.SSID + "\"";
+ config.networkId = -1;
+ mWifiManager.connectNetwork(config);
+ sleep(ConnectivityManagerTestActivity.SHORT_TIMEOUT,
+ "interruped while connecting to " + config.SSID);
+ }
+ }
+
/**
* Connect to the provided Wi-Fi network
* @param config is the network configuration
@@ -103,32 +148,40 @@ public class WifiConnectionTest
mAct.connectToWifiWithConfiguration(config));
// step 2: verify Wifi state and network state;
- assertTrue(mAct.waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
- ConnectivityManagerTestActivity.SHORT_TIMEOUT));
assertTrue(mAct.waitForNetworkState(ConnectivityManager.TYPE_WIFI,
- State.CONNECTED, ConnectivityManagerTestActivity.LONG_TIMEOUT));
+ State.CONNECTED, 2 * ConnectivityManagerTestActivity.LONG_TIMEOUT));
// step 3: verify the current connected network is the given SSID
+ assertNotNull("Wifi connection returns null", mAct.mWifiManager.getConnectionInfo());
if (DEBUG) {
- Log.v(TAG, "config.SSID = " + config.SSID);
- Log.v(TAG, "mAct.mWifiManager.getConnectionInfo.getSSID()" +
+ log("config.SSID = " + config.SSID);
+ log("mAct.mWifiManager.getConnectionInfo.getSSID()" +
mAct.mWifiManager.getConnectionInfo().getSSID());
}
assertTrue(config.SSID.contains(mAct.mWifiManager.getConnectionInfo().getSSID()));
+ }
- // Maintain the connection for 50 seconds before switching
+ private void sleep(long sometime, String errorMsg) {
try {
- Thread.sleep(50*1000);
- } catch (Exception e) {
- fail("interrupted while waiting for WPA_SUPPLICANT to start");
+ Thread.sleep(sometime);
+ } catch (InterruptedException e) {
+ fail(errorMsg);
}
}
+ private void log(String message) {
+ Log.v(TAG, message);
+ }
+
@LargeTest
public void testWifiConnections() {
for (int i = 0; i < networks.size(); i++) {
+ String ssid = networks.get(i).SSID;
+ log("-- START Wi-Fi connection test to : " + ssid + " --");
connectToWifi(networks.get(i));
- mAct.removeConfiguredNetworksAndDisableWifi();
+ sleep(2 * ConnectivityManagerTestActivity.SHORT_TIMEOUT,
+ "interruped while waiting for wifi disabled.");
+ log("-- END Wi-Fi connection test to " + ssid + " -- ");
}
}
}
diff --git a/data/keyboards/Logitech_USB_Receiver.kl b/data/keyboards/Vendor_046d_Product_c532.kl
index aa7c0ee..741c2e1 100644
--- a/data/keyboards/Logitech_USB_Receiver.kl
+++ b/data/keyboards/Vendor_046d_Product_c532.kl
@@ -13,7 +13,7 @@
# limitations under the License.
#
-# Logitech Revue keyboard
+# Logitech Revue Wireless keyboard
#
# Notes:
# - The GRAVE key is emulated by the keyboard.
diff --git a/data/keyboards/Apple_Wireless_Keyboard.kl b/data/keyboards/Vendor_05ac_Product_0239.kl
index 5234d58..5234d58 100644
--- a/data/keyboards/Apple_Wireless_Keyboard.kl
+++ b/data/keyboards/Vendor_05ac_Product_0239.kl
diff --git a/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl b/data/keyboards/Vendor_22b8_Product_093d.kl
index 87b3c32..87b3c32 100644
--- a/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl
+++ b/data/keyboards/Vendor_22b8_Product_093d.kl
diff --git a/data/keyboards/common.mk b/data/keyboards/common.mk
index 5c2a75d..56c287a 100644
--- a/data/keyboards/common.mk
+++ b/data/keyboards/common.mk
@@ -16,16 +16,20 @@
# Used by Android.mk and keyboards.mk.
keylayouts := \
- Apple_Wireless_Keyboard.kl \
- AVRCP.kl \
Generic.kl \
- Logitech_USB_Receiver.kl \
- Motorola_Bluetooth_Wireless_Keyboard.kl \
+ AVRCP.kl \
qwerty.kl \
- qwerty2.kl
+ Vendor_046d_Product_c532.kl \
+ Vendor_05ac_Product_0239.kl \
+ Vendor_22b8_Product_093d.kl
keycharmaps := \
Generic.kcm \
+ Virtual.kcm \
qwerty.kcm \
- qwerty2.kcm \
- Virtual.kcm
+ qwerty2.kcm
+
+keyconfigs := \
+ qwerty.idc \
+ qwerty2.idc
+
diff --git a/data/keyboards/keyboards.mk b/data/keyboards/keyboards.mk
index b32e436..564f41c 100644
--- a/data/keyboards/keyboards.mk
+++ b/data/keyboards/keyboards.mk
@@ -22,4 +22,8 @@ PRODUCT_COPY_FILES := $(foreach file,$(keylayouts),\
PRODUCT_COPY_FILES += $(foreach file,$(keycharmaps),\
frameworks/base/data/keyboards/$(file):system/usr/keychars/$(file))
-PRODUCT_PACKAGES := $(keylayouts) $(keycharmaps)
+PRODUCT_COPY_FILES += $(foreach file,$(keyconfigs),\
+ frameworks/base/data/keyboards/$(file):system/usr/idc/$(file))
+
+PRODUCT_PACKAGES := $(keylayouts) $(keycharmaps) $(keyconfigs)
+
diff --git a/data/keyboards/qwerty.idc b/data/keyboards/qwerty.idc
new file mode 100644
index 0000000..129b0bc
--- /dev/null
+++ b/data/keyboards/qwerty.idc
@@ -0,0 +1,23 @@
+# 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.
+
+#
+# Emulator keyboard configuration file #1.
+#
+
+keyboard.layout = qwerty
+keyboard.characterMap = qwerty
+keyboard.orientationAware = 1
+keyboard.builtIn = 1
+
diff --git a/data/keyboards/qwerty2.idc b/data/keyboards/qwerty2.idc
new file mode 100644
index 0000000..1a795c6
--- /dev/null
+++ b/data/keyboards/qwerty2.idc
@@ -0,0 +1,23 @@
+# 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.
+
+#
+# Emulator keyboard configuration file #2.
+#
+
+keyboard.layout = qwerty
+keyboard.characterMap = qwerty2
+keyboard.orientationAware = 1
+keyboard.builtIn = 1
+
diff --git a/data/keyboards/qwerty2.kl b/data/keyboards/qwerty2.kl
deleted file mode 100644
index 863a258..0000000
--- a/data/keyboards/qwerty2.kl
+++ /dev/null
@@ -1,109 +0,0 @@
-# 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.
-
-#
-# Emulator keyboard layout #2.
-#
-
-key 399 GRAVE
-key 2 1
-key 3 2
-key 4 3
-key 5 4
-key 6 5
-key 7 6
-key 8 7
-key 9 8
-key 10 9
-key 11 0
-key 158 BACK WAKE_DROPPED
-key 230 SOFT_RIGHT WAKE
-key 60 SOFT_RIGHT WAKE
-key 107 ENDCALL WAKE_DROPPED
-key 62 ENDCALL WAKE_DROPPED
-key 229 MENU WAKE_DROPPED
-key 139 MENU WAKE_DROPPED
-key 59 MENU WAKE_DROPPED
-key 127 SEARCH WAKE_DROPPED
-key 217 SEARCH WAKE_DROPPED
-key 228 POUND
-key 227 STAR
-key 231 CALL WAKE_DROPPED
-key 61 CALL WAKE_DROPPED
-key 232 DPAD_CENTER WAKE_DROPPED
-key 108 DPAD_DOWN WAKE_DROPPED
-key 103 DPAD_UP WAKE_DROPPED
-key 102 HOME WAKE
-key 105 DPAD_LEFT WAKE_DROPPED
-key 106 DPAD_RIGHT WAKE_DROPPED
-key 115 VOLUME_UP WAKE
-key 114 VOLUME_DOWN WAKE
-key 116 POWER WAKE
-key 212 CAMERA
-
-key 16 Q
-key 17 W
-key 18 E
-key 19 R
-key 20 T
-key 21 Y
-key 22 U
-key 23 I
-key 24 O
-key 25 P
-key 26 LEFT_BRACKET
-key 27 RIGHT_BRACKET
-key 43 BACKSLASH
-
-key 30 A
-key 31 S
-key 32 D
-key 33 F
-key 34 G
-key 35 H
-key 36 J
-key 37 K
-key 38 L
-key 39 SEMICOLON
-key 40 APOSTROPHE
-key 14 DEL
-
-key 44 Z
-key 45 X
-key 46 C
-key 47 V
-key 48 B
-key 49 N
-key 50 M
-key 51 COMMA
-key 52 PERIOD
-key 53 SLASH
-key 28 ENTER
-
-key 56 ALT_LEFT
-key 100 ALT_RIGHT
-key 42 SHIFT_LEFT
-key 54 SHIFT_RIGHT
-key 15 TAB
-key 57 SPACE
-key 150 EXPLORER
-key 155 ENVELOPE
-
-key 12 MINUS
-key 13 EQUALS
-key 215 AT
-
-# On an AT keyboard: ESC, F10
-key 1 BACK WAKE_DROPPED
-key 68 MENU WAKE_DROPPED
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 62fbfb4..e3bb6eb 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1818,6 +1818,7 @@ public class Paint {
nativeGetCharArrayBounds(mNativePaint, text, index, count, bounds);
}
+ @Override
protected void finalize() throws Throwable {
finalizer(mNativePaint);
}
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index 6c798a6..6c6c297 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -18,8 +18,11 @@
#ifndef _RUNTIME_EVENT_HUB_H
#define _RUNTIME_EVENT_HUB_H
-#include <android/input.h>
+#include <ui/Input.h>
#include <ui/Keyboard.h>
+#include <ui/KeyLayoutMap.h>
+#include <ui/KeyCharacterMap.h>
+#include <ui/VirtualKeyMap.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <utils/Log.h>
@@ -27,6 +30,7 @@
#include <utils/List.h>
#include <utils/Errors.h>
#include <utils/PropertyMap.h>
+#include <utils/Vector.h>
#include <linux/input.h>
@@ -59,8 +63,6 @@ struct pollfd;
namespace android {
-class KeyLayoutMap;
-
/*
* A raw event as retrieved from the EventHub.
*/
@@ -194,6 +196,9 @@ public:
virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
+ virtual void getVirtualKeyDefinitions(int32_t deviceId,
+ Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
+
virtual void dump(String8& dump) = 0;
};
@@ -230,6 +235,9 @@ public:
virtual bool hasLed(int32_t deviceId, int32_t led) const;
virtual void setLedState(int32_t deviceId, int32_t led, bool on);
+ virtual void getVirtualKeyDefinitions(int32_t deviceId,
+ Vector<VirtualKeyDefinition>& outVirtualKeys) const;
+
virtual void dump(String8& dump);
protected:
@@ -238,78 +246,80 @@ protected:
private:
bool openPlatformInput(void);
- int openDevice(const char *device);
- int closeDevice(const char *device);
+ int openDevice(const char *devicePath);
+ int closeDevice(const char *devicePath);
int scanDir(const char *dirname);
int readNotify(int nfd);
status_t mError;
- struct device_t {
- const int32_t id;
- const String8 path;
- String8 name;
- uint32_t classes;
- uint8_t* keyBitmask;
- KeyLayoutMap* layoutMap;
- String8 configurationFile;
- PropertyMap* configuration;
- KeyMapInfo keyMapInfo;
- int fd;
- device_t* next;
-
- device_t(int32_t _id, const char* _path, const char* name);
- ~device_t();
+ struct Device {
+ Device* next;
+
+ int fd;
+ const int32_t id;
+ const String8 path;
+ const InputDeviceIdentifier identifier;
+
+ uint32_t classes;
+ uint8_t* keyBitmask;
+ String8 configurationFile;
+ PropertyMap* configuration;
+ VirtualKeyMap* virtualKeyMap;
+ KeyMap keyMap;
+
+ Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
+ ~Device();
+
+ void close();
};
- device_t* getDeviceLocked(int32_t deviceId) const;
- bool hasKeycodeLocked(device_t* device, int keycode) const;
+ Device* getDeviceLocked(int32_t deviceId) const;
+ bool hasKeycodeLocked(Device* device, int keycode) const;
- int32_t getScanCodeStateLocked(device_t* device, int32_t scanCode) const;
- int32_t getKeyCodeStateLocked(device_t* device, int32_t keyCode) const;
- int32_t getSwitchStateLocked(device_t* device, int32_t sw) const;
- bool markSupportedKeyCodesLocked(device_t* device, size_t numCodes,
+ int32_t getScanCodeStateLocked(Device* device, int32_t scanCode) const;
+ int32_t getKeyCodeStateLocked(Device* device, int32_t keyCode) const;
+ int32_t getSwitchStateLocked(Device* device, int32_t sw) const;
+ bool markSupportedKeyCodesLocked(Device* device, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags) const;
- void loadConfiguration(device_t* device);
- void configureKeyMap(device_t* device);
- void setKeyboardProperties(device_t* device, bool firstKeyboard);
- void clearKeyboardProperties(device_t* device, bool firstKeyboard);
+ void loadConfiguration(Device* device);
+ status_t loadVirtualKeyMap(Device* device);
+ status_t loadKeyMap(Device* device);
+ void setKeyboardProperties(Device* device, bool builtInKeyboard);
+ void clearKeyboardProperties(Device* device, bool builtInKeyboard);
// Protect all internal state.
- mutable Mutex mLock;
-
- bool mHaveFirstKeyboard;
- int32_t mFirstKeyboardId; // the API is that the built-in keyboard is id 0, so map it
-
- struct device_ent {
- device_t* device;
- uint32_t seq;
- };
- device_ent *mDevicesById;
- int mNumDevicesById;
-
- device_t *mOpeningDevices;
- device_t *mClosingDevices;
-
- device_t **mDevices;
- struct pollfd *mFDs;
- int mFDCount;
+ mutable Mutex mLock;
+
+ // The actual id of the built-in keyboard, or -1 if none.
+ // EventHub remaps the built-in keyboard to id 0 externally as required by the API.
+ int32_t mBuiltInKeyboardId;
+
+ int32_t mNextDeviceId;
+
+ // Parallel arrays of fds and devices.
+ // First index is reserved for inotify.
+ Vector<struct pollfd> mFds;
+ Vector<Device*> mDevices;
+
+ Device *mOpeningDevices;
+ Device *mClosingDevices;
- bool mOpened;
- bool mNeedToSendFinishedDeviceScan;
- List<String8> mExcludedDevices;
+ bool mOpened;
+ bool mNeedToSendFinishedDeviceScan;
+ List<String8> mExcludedDevices;
// device ids that report particular switches.
#ifdef EV_SW
- int32_t mSwitches[SW_MAX + 1];
+ int32_t mSwitches[SW_MAX + 1];
#endif
static const int INPUT_BUFFER_SIZE = 64;
struct input_event mInputBufferData[INPUT_BUFFER_SIZE];
- int32_t mInputBufferIndex;
- int32_t mInputBufferCount;
- int32_t mInputDeviceIndex;
+ size_t mInputBufferIndex;
+ size_t mInputBufferCount;
+ size_t mInputFdIndex;
};
}; // namespace android
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 4dc8f2a..27f65bc 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -497,6 +497,23 @@ private:
KeyedVector<int32_t, MotionRange> mMotionRanges;
};
+/*
+ * Identifies a device.
+ */
+struct InputDeviceIdentifier {
+ inline InputDeviceIdentifier() :
+ bus(0), vendor(0), product(0), version(0) {
+ }
+
+ String8 name;
+ String8 location;
+ String8 uniqueId;
+ uint16_t bus;
+ uint16_t vendor;
+ uint16_t product;
+ uint16_t version;
+};
+
/* Types of input device configuration files. */
enum InputDeviceConfigurationFileType {
INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0, /* .idc file */
@@ -505,13 +522,28 @@ enum InputDeviceConfigurationFileType {
};
/*
- * Get the path of an input device configuration file, if one is available.
- * Spaces in the name are replaced with underscores.
+ * 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 getInputDeviceConfigurationFilePath(
+extern String8 getInputDeviceConfigurationFilePathByName(
const String8& name, InputDeviceConfigurationFileType type);
} // namespace android
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index cfceaab..8ec5421 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -35,17 +35,6 @@ namespace android {
class InputDevice;
class InputMapper;
-/* Describes a virtual key. */
-struct VirtualKeyDefinition {
- int32_t scanCode;
-
- // configured position data, specified in display coords
- int32_t centerX;
- int32_t centerY;
- int32_t width;
- int32_t height;
-};
-
/*
* Input reader policy interface.
@@ -86,10 +75,6 @@ public:
*/
virtual bool filterJumpyTouchEvents() = 0;
- /* Gets the configured virtual key definitions for an input device. */
- virtual void getVirtualKeyDefinitions(const String8& deviceName,
- Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0;
-
/* Gets the excluded device names for the platform. */
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
};
diff --git a/include/ui/Keyboard.h b/include/ui/Keyboard.h
index 689607d..50296e2 100644
--- a/include/ui/Keyboard.h
+++ b/include/ui/Keyboard.h
@@ -33,30 +33,58 @@ enum {
DEVICE_ID_VIRTUAL_KEYBOARD = -1,
};
-struct KeyMapInfo {
+class KeyLayoutMap;
+class KeyCharacterMap;
+
+/**
+ * Loads the key layout map and key character map for a keyboard device.
+ */
+class KeyMap {
+public:
String8 keyLayoutFile;
+ KeyLayoutMap* keyLayoutMap;
+
String8 keyCharacterMapFile;
- bool isDefaultKeyMap;
+ KeyCharacterMap* keyCharacterMap;
+
+ KeyMap();
+ ~KeyMap();
- KeyMapInfo() : isDefaultKeyMap(false) {
+ status_t load(const InputDeviceIdentifier& deviceIdenfier,
+ const PropertyMap* deviceConfiguration);
+
+ inline bool haveKeyLayout() const {
+ return !keyLayoutFile.isEmpty();
+ }
+
+ inline bool haveKeyCharacterMap() const {
+ return !keyCharacterMapFile.isEmpty();
}
- bool isComplete() {
- return !keyLayoutFile.isEmpty() && !keyCharacterMapFile.isEmpty();
+ inline bool isComplete() const {
+ return haveKeyLayout() && haveKeyCharacterMap();
}
+
+private:
+ bool probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const String8& name);
+ status_t loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, const String8& name);
+ status_t loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
+ const String8& name);
+ String8 getPath(const InputDeviceIdentifier& deviceIdentifier,
+ const String8& name, InputDeviceConfigurationFileType type);
};
/**
- * Resolves the key map to use for a particular keyboard device.
+ * Returns true if the keyboard is eligible for use as a built-in keyboard.
*/
-extern status_t resolveKeyMap(const String8& deviceName,
- const PropertyMap* deviceConfiguration, KeyMapInfo& outKeyMapInfo);
+extern bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier,
+ const PropertyMap* deviceConfiguration, const KeyMap* keyMap);
/**
* Sets keyboard system properties.
*/
-extern void setKeyboardProperties(int32_t deviceId, const String8& deviceName,
- const KeyMapInfo& keyMapInfo);
+extern void setKeyboardProperties(int32_t deviceId, const InputDeviceIdentifier& deviceIdentifier,
+ const String8& keyLayoutFile, const String8& keyCharacterMapFile);
/**
* Clears keyboard system properties.
diff --git a/include/ui/VirtualKeyMap.h b/include/ui/VirtualKeyMap.h
new file mode 100644
index 0000000..7813d9d
--- /dev/null
+++ b/include/ui/VirtualKeyMap.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_VIRTUAL_KEY_MAP_H
+#define _UI_VIRTUAL_KEY_MAP_H
+
+#include <stdint.h>
+
+#include <ui/Input.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/Tokenizer.h>
+#include <utils/String8.h>
+#include <utils/Unicode.h>
+
+namespace android {
+
+/* Describes a virtual key. */
+struct VirtualKeyDefinition {
+ int32_t scanCode;
+
+ // configured position data, specified in display coords
+ int32_t centerX;
+ int32_t centerY;
+ int32_t width;
+ int32_t height;
+};
+
+
+/**
+ * Describes a collection of virtual keys on a touch screen in terms of
+ * virtual scan codes and hit rectangles.
+ */
+class VirtualKeyMap {
+public:
+ ~VirtualKeyMap();
+
+ static status_t load(const String8& filename, VirtualKeyMap** outMap);
+
+ inline const Vector<VirtualKeyDefinition>& getVirtualKeys() const {
+ return mVirtualKeys;
+ }
+
+private:
+ class Parser {
+ VirtualKeyMap* mMap;
+ Tokenizer* mTokenizer;
+
+ public:
+ Parser(VirtualKeyMap* map, Tokenizer* tokenizer);
+ ~Parser();
+ status_t parse();
+
+ private:
+ bool consumeFieldDelimiterAndSkipWhitespace();
+ bool parseNextIntField(int32_t* outValue);
+ };
+
+ Vector<VirtualKeyDefinition> mVirtualKeys;
+
+ VirtualKeyMap();
+};
+
+} // namespace android
+
+#endif // _UI_KEY_CHARACTER_MAP_H
diff --git a/include/utils/String8.h b/include/utils/String8.h
index 6abfb06..6b49ff5 100644
--- a/include/utils/String8.h
+++ b/include/utils/String8.h
@@ -47,7 +47,12 @@ public:
explicit String8(const char32_t* o);
explicit String8(const char32_t* o, size_t numChars);
~String8();
-
+
+ static inline const String8 empty();
+
+ static String8 format(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
+ static String8 formatV(const char* fmt, va_list args);
+
inline const char* string() const;
inline size_t size() const;
inline size_t length() const;
@@ -229,6 +234,10 @@ inline int strictly_order_type(const String8& lhs, const String8& rhs)
return compare_type(lhs, rhs) < 0;
}
+inline const String8 String8::empty() {
+ return String8();
+}
+
inline const char* String8::string() const
{
return mString;
diff --git a/include/utils/Tokenizer.h b/include/utils/Tokenizer.h
index 21e58e6..c7db5fb 100644
--- a/include/utils/Tokenizer.h
+++ b/include/utils/Tokenizer.h
@@ -28,7 +28,7 @@ namespace android {
* A simple tokenizer for loading and parsing ASCII text files line by line.
*/
class Tokenizer {
- Tokenizer(const String8& filename, FileMap* fileMap, const char* buffer, size_t length);
+ Tokenizer(const String8& filename, FileMap* fileMap, char* buffer, size_t length);
public:
~Tokenizer();
@@ -110,7 +110,7 @@ private:
String8 mFilename;
FileMap* mFileMap;
- const char* mBuffer;
+ char* mBuffer;
size_t mLength;
const char* mCurrent;
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 5948e04..d0e041a 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -21,6 +21,7 @@ commonSources:= \
Keyboard.cpp \
KeyLayoutMap.cpp \
KeyCharacterMap.cpp \
+ VirtualKeyMap.cpp
# For the host
# =====================================================
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index b312cda..8f4bac6 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -33,6 +33,8 @@
#include <assert.h>
#include <ui/KeyLayoutMap.h>
+#include <ui/KeyCharacterMap.h>
+#include <ui/VirtualKeyMap.h>
#include <string.h>
#include <stdint.h>
@@ -56,10 +58,6 @@
/* this macro computes the number of bytes needed to represent a bit array of the specified size */
#define sizeof_bit_array(bits) ((bits + 7) / 8)
-#define ID_MASK 0x0000ffff
-#define SEQ_MASK 0x7fff0000
-#define SEQ_SHIFT 16
-
#ifndef ABS_MT_TOUCH_MAJOR
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#endif
@@ -72,6 +70,9 @@
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
#endif
+// Fd at index 0 is always reserved for inotify
+#define FIRST_ACTUAL_DEVICE_INDEX 1
+
#define INDENT " "
#define INDENT2 " "
#define INDENT3 " "
@@ -79,7 +80,7 @@
namespace android {
static const char *WAKE_LOCK_ID = "KeyEvents";
-static const char *device_path = "/dev/input";
+static const char *DEVICE_PATH = "/dev/input";
/* return the larger integer */
static inline int max(int v1, int v2)
@@ -91,63 +92,69 @@ static inline const char* toString(bool value) {
return value ? "true" : "false";
}
-EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name)
- : id(_id), path(_path), name(name), classes(0)
- , keyBitmask(NULL), layoutMap(NULL), configuration(NULL), fd(-1), next(NULL) {
+// --- EventHub::Device ---
+
+EventHub::Device::Device(int fd, int32_t id, const String8& path,
+ const InputDeviceIdentifier& identifier) :
+ next(NULL),
+ fd(fd), id(id), path(path), identifier(identifier),
+ classes(0), keyBitmask(NULL), configuration(NULL), virtualKeyMap(NULL) {
}
-EventHub::device_t::~device_t() {
- delete [] keyBitmask;
- delete layoutMap;
+EventHub::Device::~Device() {
+ close();
+ delete[] keyBitmask;
delete configuration;
+ delete virtualKeyMap;
}
-EventHub::EventHub(void)
- : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(-1)
- , mDevicesById(0), mNumDevicesById(0)
- , mOpeningDevices(0), mClosingDevices(0)
- , mDevices(0), mFDs(0), mFDCount(0), mOpened(false), mNeedToSendFinishedDeviceScan(false)
- , mInputBufferIndex(0), mInputBufferCount(0), mInputDeviceIndex(0)
-{
+void EventHub::Device::close() {
+ if (fd >= 0) {
+ ::close(fd);
+ fd = -1;
+ }
+}
+
+
+// --- EventHub ---
+
+EventHub::EventHub(void) :
+ mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
+ mOpeningDevices(0), mClosingDevices(0),
+ mOpened(false), mNeedToSendFinishedDeviceScan(false),
+ mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
#ifdef EV_SW
memset(mSwitches, 0, sizeof(mSwitches));
#endif
}
-/*
- * Clean up.
- */
-EventHub::~EventHub(void)
-{
+EventHub::~EventHub(void) {
release_wake_lock(WAKE_LOCK_ID);
// we should free stuff here...
}
-status_t EventHub::errorCheck() const
-{
+status_t EventHub::errorCheck() const {
return mError;
}
-String8 EventHub::getDeviceName(int32_t deviceId) const
-{
+String8 EventHub::getDeviceName(int32_t deviceId) const {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device == NULL) return String8();
- return device->name;
+ return device->identifier.name;
}
-uint32_t EventHub::getDeviceClasses(int32_t deviceId) const
-{
+uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device == NULL) return 0;
return device->classes;
}
void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device && device->configuration) {
*outConfiguration = *device->configuration;
} else {
@@ -160,14 +167,14 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
outAxisInfo->clear();
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device == NULL) return -1;
struct input_absinfo info;
if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
LOGW("Error reading absolute controller %d for device %s fd %d\n",
- axis, device->name.string(), device->fd);
+ axis, device->identifier.name.string(), device->fd);
return -errno;
}
@@ -185,7 +192,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
if (scanCode >= 0 && scanCode <= KEY_MAX) {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device != NULL) {
return getScanCodeStateLocked(device, scanCode);
}
@@ -193,7 +200,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
return AKEY_STATE_UNKNOWN;
}
-int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
+int32_t EventHub::getScanCodeStateLocked(Device* device, int32_t scanCode) const {
uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
if (ioctl(device->fd,
@@ -206,20 +213,20 @@ int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) con
int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device != NULL) {
return getKeyCodeStateLocked(device, keyCode);
}
return AKEY_STATE_UNKNOWN;
}
-int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const {
- if (!device->layoutMap) {
+int32_t EventHub::getKeyCodeStateLocked(Device* device, int32_t keyCode) const {
+ if (!device->keyMap.haveKeyLayout()) {
return AKEY_STATE_UNKNOWN;
}
Vector<int32_t> scanCodes;
- device->layoutMap->findScanCodes(keyCode, &scanCodes);
+ device->keyMap.keyLayoutMap->findScanCodes(keyCode, &scanCodes);
uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
memset(key_bitmask, 0, sizeof(key_bitmask));
@@ -247,7 +254,7 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
if (sw >= 0 && sw <= SW_MAX) {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device != NULL) {
return getSwitchStateLocked(device, sw);
}
@@ -256,7 +263,7 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
return AKEY_STATE_UNKNOWN;
}
-int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
+int32_t EventHub::getSwitchStateLocked(Device* device, int32_t sw) const {
uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
memset(sw_bitmask, 0, sizeof(sw_bitmask));
if (ioctl(device->fd,
@@ -270,16 +277,16 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags) const {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device != NULL) {
return markSupportedKeyCodesLocked(device, numCodes, keyCodes, outFlags);
}
return false;
}
-bool EventHub::markSupportedKeyCodesLocked(device_t* device, size_t numCodes,
+bool EventHub::markSupportedKeyCodesLocked(Device* device, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags) const {
- if (device->layoutMap == NULL || device->keyBitmask == NULL) {
+ if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
return false;
}
@@ -287,7 +294,7 @@ bool EventHub::markSupportedKeyCodesLocked(device_t* device, size_t numCodes,
for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
scanCodes.clear();
- status_t err = device->layoutMap->findScanCodes(keyCodes[codeIndex], &scanCodes);
+ status_t err = device->keyMap.keyLayoutMap->findScanCodes(keyCodes[codeIndex], &scanCodes);
if (! err) {
// check the possible scan codes identified by the layout map against the
// map of codes actually emitted by the driver
@@ -306,20 +313,20 @@ status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
int32_t* outKeycode, uint32_t* outFlags) const
{
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
- if (device != NULL && device->layoutMap != NULL) {
- status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
+ if (device && device->keyMap.haveKeyLayout()) {
+ status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
if (err == NO_ERROR) {
return NO_ERROR;
}
}
- if (mHaveFirstKeyboard) {
- device = getDeviceLocked(mFirstKeyboardId);
+ if (mBuiltInKeyboardId != -1) {
+ device = getDeviceLocked(mBuiltInKeyboardId);
- if (device != NULL && device->layoutMap != NULL) {
- status_t err = device->layoutMap->map(scancode, outKeycode, outFlags);
+ if (device && device->keyMap.haveKeyLayout()) {
+ status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
if (err == NO_ERROR) {
return NO_ERROR;
}
@@ -341,7 +348,7 @@ void EventHub::addExcludedDevice(const char* deviceName)
bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device) {
uint8_t bitmask[sizeof_bit_array(LED_MAX + 1)];
memset(bitmask, 0, sizeof(bitmask));
@@ -356,7 +363,7 @@ bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
AutoMutex _l(mLock);
- device_t* device = getDeviceLocked(deviceId);
+ Device* device = getDeviceLocked(deviceId);
if (device) {
struct input_event ev;
ev.time.tv_sec = 0;
@@ -372,21 +379,33 @@ void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
}
}
-EventHub::device_t* EventHub::getDeviceLocked(int32_t deviceId) const
-{
- if (deviceId == 0) deviceId = mFirstKeyboardId;
- int32_t id = deviceId & ID_MASK;
- if (id >= mNumDevicesById || id < 0) return NULL;
- device_t* dev = mDevicesById[id].device;
- if (dev == NULL) return NULL;
- if (dev->id == deviceId) {
- return dev;
+void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
+ Vector<VirtualKeyDefinition>& outVirtualKeys) const {
+ outVirtualKeys.clear();
+
+ AutoMutex _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ if (device && device->virtualKeyMap) {
+ outVirtualKeys.appendVector(device->virtualKeyMap->getVirtualKeys());
+ }
+}
+
+EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
+ if (deviceId == 0) {
+ deviceId = mBuiltInKeyboardId;
+ }
+
+ size_t numDevices = mDevices.size();
+ for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < numDevices; i++) {
+ Device* device = mDevices[i];
+ if (device->id == deviceId) {
+ return device;
+ }
}
return NULL;
}
-bool EventHub::getEvent(RawEvent* outEvent)
-{
+bool EventHub::getEvent(RawEvent* outEvent) {
outEvent->deviceId = 0;
outEvent->type = 0;
outEvent->scanCode = 0;
@@ -407,11 +426,11 @@ bool EventHub::getEvent(RawEvent* outEvent)
for (;;) {
// Report any devices that had last been added/removed.
if (mClosingDevices != NULL) {
- device_t* device = mClosingDevices;
- LOGV("Reporting device closed: id=0x%x, name=%s\n",
+ Device* device = mClosingDevices;
+ LOGV("Reporting device closed: id=%d, name=%s\n",
device->id, device->path.string());
mClosingDevices = device->next;
- if (device->id == mFirstKeyboardId) {
+ if (device->id == mBuiltInKeyboardId) {
outEvent->deviceId = 0;
} else {
outEvent->deviceId = device->id;
@@ -424,11 +443,11 @@ bool EventHub::getEvent(RawEvent* outEvent)
}
if (mOpeningDevices != NULL) {
- device_t* device = mOpeningDevices;
- LOGV("Reporting device opened: id=0x%x, name=%s\n",
+ Device* device = mOpeningDevices;
+ LOGV("Reporting device opened: id=%d, name=%s\n",
device->id, device->path.string());
mOpeningDevices = device->next;
- if (device->id == mFirstKeyboardId) {
+ if (device->id == mBuiltInKeyboardId) {
outEvent->deviceId = 0;
} else {
outEvent->deviceId = device->id;
@@ -451,11 +470,11 @@ bool EventHub::getEvent(RawEvent* outEvent)
// Consume buffered input events, if any.
if (mInputBufferIndex < mInputBufferCount) {
const struct input_event& iev = mInputBufferData[mInputBufferIndex++];
- const device_t* device = mDevices[mInputDeviceIndex];
+ const Device* device = mDevices[mInputFdIndex];
LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(),
(int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value);
- if (device->id == mFirstKeyboardId) {
+ if (device->id == mBuiltInKeyboardId) {
outEvent->deviceId = 0;
} else {
outEvent->deviceId = device->id;
@@ -465,8 +484,8 @@ bool EventHub::getEvent(RawEvent* outEvent)
outEvent->flags = 0;
if (iev.type == EV_KEY) {
outEvent->keyCode = AKEYCODE_UNKNOWN;
- if (device->layoutMap) {
- status_t err = device->layoutMap->map(iev.code,
+ if (device->keyMap.haveKeyLayout()) {
+ status_t err = device->keyMap.keyLayoutMap->map(iev.code,
&outEvent->keyCode, &outEvent->flags);
LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
iev.code, outEvent->keyCode, outEvent->flags, err);
@@ -486,13 +505,13 @@ bool EventHub::getEvent(RawEvent* outEvent)
// Finish reading all events from devices identified in previous poll().
// This code assumes that mInputDeviceIndex is initially 0 and that the
// revents member of pollfd is initialized to 0 when the device is first added.
- // Since mFDs[0] is used for inotify, we process regular events starting at index 1.
- mInputDeviceIndex += 1;
- if (mInputDeviceIndex >= mFDCount) {
+ // Since mFds[0] is used for inotify, we process regular events starting at index 1.
+ mInputFdIndex += 1;
+ if (mInputFdIndex >= mFds.size()) {
break;
}
- const struct pollfd& pfd = mFDs[mInputDeviceIndex];
+ const struct pollfd& pfd = mFds[mInputFdIndex];
if (pfd.revents & POLLIN) {
int32_t readSize = read(pfd.fd, mInputBufferData,
sizeof(struct input_event) * INPUT_BUFFER_SIZE);
@@ -503,7 +522,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
} else if ((readSize % sizeof(struct input_event)) != 0) {
LOGE("could not get event (wrong size: %d)", readSize);
} else {
- mInputBufferCount = readSize / sizeof(struct input_event);
+ mInputBufferCount = size_t(readSize) / sizeof(struct input_event);
mInputBufferIndex = 0;
}
}
@@ -512,14 +531,14 @@ bool EventHub::getEvent(RawEvent* outEvent)
#if HAVE_INOTIFY
// readNotify() will modify mFDs and mFDCount, so this must be done after
// processing all other events.
- if(mFDs[0].revents & POLLIN) {
- readNotify(mFDs[0].fd);
- mFDs[0].revents = 0;
+ if(mFds[0].revents & POLLIN) {
+ readNotify(mFds[0].fd);
+ mFds.editItemAt(0).revents = 0;
continue; // report added or removed devices immediately
}
#endif
- mInputDeviceIndex = 0;
+ mInputFdIndex = 0;
// Poll for events. Mind the wake lock dance!
// We hold a wake lock at all times except during poll(). This works due to some
@@ -531,7 +550,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
// pending or currently being processed.
release_wake_lock(WAKE_LOCK_ID);
- int pollResult = poll(mFDs, mFDCount, -1);
+ int pollResult = poll(mFds.editArray(), mFds.size(), -1);
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
@@ -547,36 +566,37 @@ bool EventHub::getEvent(RawEvent* outEvent)
/*
* Open the platform-specific input device.
*/
-bool EventHub::openPlatformInput(void)
-{
+bool EventHub::openPlatformInput(void) {
/*
* Open platform-specific input device(s).
*/
- int res;
+ int res, fd;
- mFDCount = 1;
- mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
- mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
- mFDs[0].events = POLLIN;
- mFDs[0].revents = 0;
- mDevices[0] = NULL;
#ifdef HAVE_INOTIFY
- mFDs[0].fd = inotify_init();
- res = inotify_add_watch(mFDs[0].fd, device_path, IN_DELETE | IN_CREATE);
+ fd = inotify_init();
+ res = inotify_add_watch(fd, DEVICE_PATH, IN_DELETE | IN_CREATE);
if(res < 0) {
- LOGE("could not add watch for %s, %s\n", device_path, strerror(errno));
+ LOGE("could not add watch for %s, %s\n", DEVICE_PATH, strerror(errno));
}
#else
/*
* The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
* We allocate space for it and set it to something invalid.
*/
- mFDs[0].fd = -1;
+ fd = -1;
#endif
- res = scanDir(device_path);
+ // Reserve fd index 0 for inotify.
+ struct pollfd pollfd;
+ pollfd.fd = fd;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+ mFds.push(pollfd);
+ mDevices.push(NULL);
+
+ res = scanDir(DEVICE_PATH);
if(res < 0) {
- LOGE("scan dir failed for %s\n", device_path);
+ LOGE("scan dir failed for %s\n", DEVICE_PATH);
}
return true;
@@ -604,129 +624,102 @@ static const int32_t GAMEPAD_KEYCODES[] = {
AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE
};
-int EventHub::openDevice(const char *deviceName) {
- int version;
- int fd;
- struct pollfd *new_mFDs;
- device_t **new_devices;
- char **new_device_names;
- char name[80];
- char location[80];
- char idstr[80];
- struct input_id id;
+int EventHub::openDevice(const char *devicePath) {
+ char buffer[80];
- LOGV("Opening device: %s", deviceName);
+ LOGV("Opening device: %s", devicePath);
AutoMutex _l(mLock);
- fd = open(deviceName, O_RDWR);
+ int fd = open(devicePath, O_RDWR);
if(fd < 0) {
- LOGE("could not open %s, %s\n", deviceName, strerror(errno));
+ LOGE("could not open %s, %s\n", devicePath, strerror(errno));
return -1;
}
- if(ioctl(fd, EVIOCGVERSION, &version)) {
- LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
- return -1;
- }
- if(ioctl(fd, EVIOCGID, &id)) {
- LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
- return -1;
- }
- name[sizeof(name) - 1] = '\0';
- location[sizeof(location) - 1] = '\0';
- idstr[sizeof(idstr) - 1] = '\0';
- if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
- //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
- name[0] = '\0';
+ InputDeviceIdentifier identifier;
+
+ // Get device name.
+ if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
+ //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
+ } else {
+ buffer[sizeof(buffer) - 1] = '\0';
+ identifier.name.setTo(buffer);
}
- // check to see if the device is on our excluded list
+ // Check to see if the device is on our excluded list
List<String8>::iterator iter = mExcludedDevices.begin();
List<String8>::iterator end = mExcludedDevices.end();
for ( ; iter != end; iter++) {
const char* test = *iter;
- if (strcmp(name, test) == 0) {
- LOGI("ignoring event id %s driver %s\n", deviceName, test);
+ if (identifier.name == test) {
+ LOGI("ignoring event id %s driver %s\n", devicePath, test);
close(fd);
return -1;
}
}
- if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
- //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
- location[0] = '\0';
- }
- if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
- //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
- idstr[0] = '\0';
- }
-
- if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
- LOGE("Error %d making device file descriptor non-blocking.", errno);
+ // Get device driver version.
+ int driverVersion;
+ if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
+ LOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
close(fd);
return -1;
}
- int devid = 0;
- while (devid < mNumDevicesById) {
- if (mDevicesById[devid].device == NULL) {
- break;
- }
- devid++;
+ // Get device identifier.
+ struct input_id inputId;
+ if(ioctl(fd, EVIOCGID, &inputId)) {
+ LOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
+ close(fd);
+ return -1;
}
- if (devid >= mNumDevicesById) {
- device_ent* new_devids = (device_ent*)realloc(mDevicesById,
- sizeof(mDevicesById[0]) * (devid + 1));
- if (new_devids == NULL) {
- LOGE("out of memory");
- return -1;
- }
- mDevicesById = new_devids;
- mNumDevicesById = devid+1;
- mDevicesById[devid].device = NULL;
- mDevicesById[devid].seq = 0;
+ identifier.bus = inputId.bustype;
+ identifier.product = inputId.product;
+ identifier.vendor = inputId.vendor;
+ identifier.version = inputId.version;
+
+ // Get device physical location.
+ if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
+ //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
+ } else {
+ buffer[sizeof(buffer) - 1] = '\0';
+ identifier.location.setTo(buffer);
}
- mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
- if (mDevicesById[devid].seq == 0) {
- mDevicesById[devid].seq = 1<<SEQ_SHIFT;
+ // Get device unique id.
+ if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
+ //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
+ } else {
+ buffer[sizeof(buffer) - 1] = '\0';
+ identifier.uniqueId.setTo(buffer);
}
- new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
- new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
- if (new_mFDs == NULL || new_devices == NULL) {
- LOGE("out of memory");
+ // Make file descriptor non-blocking for use with poll().
+ if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
+ LOGE("Error %d making device file descriptor non-blocking.", errno);
+ close(fd);
return -1;
}
- mFDs = new_mFDs;
- mDevices = new_devices;
+
+ // Allocate device. (The device object takes ownership of the fd at this point.)
+ int32_t deviceId = mNextDeviceId++;
+ Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
#if 0
- LOGI("add device %d: %s\n", mFDCount, deviceName);
- LOGI(" bus: %04x\n"
- " vendor %04x\n"
- " product %04x\n"
- " version %04x\n",
- id.bustype, id.vendor, id.product, id.version);
- LOGI(" name: \"%s\"\n", name);
- LOGI(" location: \"%s\"\n"
- " id: \"%s\"\n", location, idstr);
- LOGI(" version: %d.%d.%d\n",
- version >> 16, (version >> 8) & 0xff, version & 0xff);
+ LOGI("add device %d: %s\n", deviceId, devicePath);
+ LOGI(" bus: %04x\n"
+ " vendor %04x\n"
+ " product %04x\n"
+ " version %04x\n",
+ identifier.bus, identifier.vendor, identifier.product, identifier.version);
+ LOGI(" name: \"%s\"\n", identifier.name.string());
+ LOGI(" location: \"%s\"\n", identifier.location.string());
+ LOGI(" unique id: \"%s\"\n", identifier.uniqueId.string());
+ LOGI(" driver: v%d.%d.%d\n",
+ driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
#endif
- device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
- if (device == NULL) {
- LOGE("out of memory");
- return -1;
- }
-
- device->fd = fd;
- mFDs[mFDCount].fd = fd;
- mFDs[mFDCount].events = POLLIN;
- mFDs[mFDCount].revents = 0;
-
// Load the configuration file for the device.
loadConfiguration(device);
@@ -798,7 +791,7 @@ int EventHub::openDevice(const char *deviceName) {
bool hasSwitches = false;
if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
for (int i=0; i<EV_SW; i++) {
- //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
+ //LOGI("Device %d sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
if (test_bit(i, sw_bitmask)) {
hasSwitches = true;
if (mSwitches[i] == 0) {
@@ -812,37 +805,29 @@ int EventHub::openDevice(const char *deviceName) {
}
#endif
- if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
- // a more descriptive name
- device->name = name;
-
- // Configure the keymap for the device.
- configureKeyMap(device);
-
- // Tell the world about the devname (the descriptive name)
- if (!mHaveFirstKeyboard && !device->keyMapInfo.isDefaultKeyMap && strstr(name, "-keypad")) {
- // the built-in keyboard has a well-known device ID of 0,
- // this device better not go away.
- mHaveFirstKeyboard = true;
- mFirstKeyboardId = device->id;
- setKeyboardProperties(device, true);
- } else {
- // ensure mFirstKeyboardId is set to -something-.
- if (mFirstKeyboardId == -1) {
- mFirstKeyboardId = device->id;
- setKeyboardProperties(device, true);
- }
+ if ((device->classes & INPUT_DEVICE_CLASS_TOUCHSCREEN)) {
+ // Load the virtual keys for the touch screen, if any.
+ // We do this now so that we can make sure to load the keymap if necessary.
+ status_t status = loadVirtualKeyMap(device);
+ if (!status) {
+ device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
}
+ }
+
+ if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
+ // Load the keymap for the device.
+ status_t status = loadKeyMap(device);
+
+ // Set system properties for the keyboard.
setKeyboardProperties(device, false);
- // Load the keylayout.
- if (!device->keyMapInfo.keyLayoutFile.isEmpty()) {
- status_t status = KeyLayoutMap::load(device->keyMapInfo.keyLayoutFile,
- &device->layoutMap);
- if (status) {
- LOGE("Error %d loading key layout file '%s'.", status,
- device->keyMapInfo.keyLayoutFile.string());
- }
+ // Register the keyboard as a built-in keyboard if it is eligible.
+ if (!status
+ && mBuiltInKeyboardId == -1
+ && isEligibleBuiltInKeyboard(device->identifier,
+ device->configuration, &device->keyMap)) {
+ mBuiltInKeyboardId = device->id;
+ setKeyboardProperties(device, true);
}
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
@@ -866,76 +851,87 @@ int EventHub::openDevice(const char *deviceName) {
break;
}
}
-
- LOGI("New keyboard: device->id=0x%x devname='%s' keylayout='%s' keycharactermap='%s'\n",
- device->id, name,
- device->keyMapInfo.keyLayoutFile.string(),
- device->keyMapInfo.keyCharacterMapFile.string());
}
// If the device isn't recognized as something we handle, don't monitor it.
if (device->classes == 0) {
- LOGV("Dropping device %s %p, id = %d\n", deviceName, device, devid);
- close(fd);
+ LOGV("Dropping device: id=%d, path='%s', name='%s'",
+ deviceId, devicePath, device->identifier.name.string());
delete device;
return -1;
}
- LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x "
- "configuration='%s'\n",
- deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes,
- device->configurationFile.string());
-
- LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
- deviceName, device, mFDCount, devid, device->classes);
+ LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
+ "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
+ deviceId, fd, devicePath, device->identifier.name.string(),
+ device->classes,
+ device->configurationFile.string(),
+ device->keyMap.keyLayoutFile.string(),
+ device->keyMap.keyCharacterMapFile.string(),
+ toString(mBuiltInKeyboardId == deviceId));
+
+ struct pollfd pollfd;
+ pollfd.fd = fd;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+ mFds.push(pollfd);
+ mDevices.push(device);
- mDevicesById[devid].device = device;
device->next = mOpeningDevices;
mOpeningDevices = device;
- mDevices[mFDCount] = device;
-
- mFDCount++;
return 0;
}
-void EventHub::loadConfiguration(device_t* device) {
- device->configurationFile = getInputDeviceConfigurationFilePath(device->name,
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
+void EventHub::loadConfiguration(Device* device) {
+ device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
+ device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
if (device->configurationFile.isEmpty()) {
- LOGI("No input device configuration file found for device '%s'.",
- device->name.string());
+ LOGD("No input device configuration file found for device '%s'.",
+ device->identifier.name.string());
} else {
status_t status = PropertyMap::load(device->configurationFile,
&device->configuration);
if (status) {
- LOGE("Error loading input device configuration file for device '%s'.",
- device->name.string());
+ LOGE("Error loading input device configuration file for device '%s'. "
+ "Using default configuration.",
+ device->identifier.name.string());
}
}
}
-void EventHub::configureKeyMap(device_t* device) {
- android::resolveKeyMap(device->name, device->configuration, device->keyMapInfo);
+status_t EventHub::loadVirtualKeyMap(Device* device) {
+ // The virtual key map is supplied by the kernel as a system board property file.
+ String8 path;
+ path.append("/sys/board_properties/virtualkeys.");
+ path.append(device->identifier.name);
+ if (access(path.string(), R_OK)) {
+ return NAME_NOT_FOUND;
+ }
+ return VirtualKeyMap::load(path, &device->virtualKeyMap);
}
-void EventHub::setKeyboardProperties(device_t* device, bool firstKeyboard) {
- int32_t id = firstKeyboard ? 0 : device->id;
- android::setKeyboardProperties(id, device->name, device->keyMapInfo);
+status_t EventHub::loadKeyMap(Device* device) {
+ return device->keyMap.load(device->identifier, device->configuration);
}
-void EventHub::clearKeyboardProperties(device_t* device, bool firstKeyboard) {
- int32_t id = firstKeyboard ? 0 : device->id;
+void EventHub::setKeyboardProperties(Device* device, bool builtInKeyboard) {
+ int32_t id = builtInKeyboard ? 0 : device->id;
+ android::setKeyboardProperties(id, device->identifier,
+ device->keyMap.keyLayoutFile, device->keyMap.keyCharacterMapFile);
+}
+
+void EventHub::clearKeyboardProperties(Device* device, bool builtInKeyboard) {
+ int32_t id = builtInKeyboard ? 0 : device->id;
android::clearKeyboardProperties(id);
}
-bool EventHub::hasKeycodeLocked(device_t* device, int keycode) const
-{
- if (device->keyBitmask == NULL || device->layoutMap == NULL) {
+bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
+ if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
return false;
}
Vector<int32_t> scanCodes;
- device->layoutMap->findScanCodes(keycode, &scanCodes);
+ device->keyMap.keyLayoutMap->findScanCodes(keycode, &scanCodes);
const size_t N = scanCodes.size();
for (size_t i=0; i<N && i<=KEY_MAX; i++) {
int32_t sc = scanCodes.itemAt(i);
@@ -947,29 +943,15 @@ bool EventHub::hasKeycodeLocked(device_t* device, int keycode) const
return false;
}
-int EventHub::closeDevice(const char *deviceName) {
+int EventHub::closeDevice(const char *devicePath) {
AutoMutex _l(mLock);
- int i;
- for(i = 1; i < mFDCount; i++) {
- if(strcmp(mDevices[i]->path.string(), deviceName) == 0) {
- //LOGD("remove device %d: %s\n", i, deviceName);
- device_t* device = mDevices[i];
-
- LOGI("Removed device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
- device->path.string(), device->name.string(), device->id,
- mNumDevicesById, mFDCount, mFDs[i].fd, device->classes);
-
- // Clear this device's entry.
- int index = (device->id&ID_MASK);
- mDevicesById[index].device = NULL;
-
- // Close the file descriptor and compact the fd array.
- close(mFDs[i].fd);
- int count = mFDCount - i - 1;
- memmove(mDevices + i, mDevices + i + 1, sizeof(mDevices[0]) * count);
- memmove(mFDs + i, mFDs + i + 1, sizeof(mFDs[0]) * count);
- mFDCount--;
+ for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
+ Device* device = mDevices[i];
+ if (device->path == devicePath) {
+ LOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
+ device->path.string(), device->identifier.name.string(), device->id,
+ device->fd, device->classes);
#ifdef EV_SW
for (int j=0; j<EV_SW; j++) {
@@ -978,21 +960,25 @@ int EventHub::closeDevice(const char *deviceName) {
}
}
#endif
-
- device->next = mClosingDevices;
- mClosingDevices = device;
- if (device->id == mFirstKeyboardId) {
+ if (device->id == mBuiltInKeyboardId) {
LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
- device->path.string(), mFirstKeyboardId);
- mFirstKeyboardId = -1;
+ device->path.string(), mBuiltInKeyboardId);
+ mBuiltInKeyboardId = -1;
clearKeyboardProperties(device, true);
}
clearKeyboardProperties(device, false);
+
+ mFds.removeAt(i);
+ mDevices.removeAt(i);
+ device->close();
+
+ device->next = mClosingDevices;
+ mClosingDevices = device;
return 0;
}
}
- LOGE("remove device: %s not found\n", deviceName);
+ LOGE("remove device: %s not found\n", devicePath);
return -1;
}
@@ -1016,7 +1002,7 @@ int EventHub::readNotify(int nfd) {
}
//printf("got %d bytes of event information\n", res);
- strcpy(devname, device_path);
+ strcpy(devname, DEVICE_PATH);
filename = devname + strlen(devname);
*filename++ = '/';
@@ -1040,7 +1026,6 @@ int EventHub::readNotify(int nfd) {
return 0;
}
-
int EventHub::scanDir(const char *dirname)
{
char devname[PATH_MAX];
@@ -1071,28 +1056,32 @@ void EventHub::dump(String8& dump) {
{ // acquire lock
AutoMutex _l(mLock);
- dump.appendFormat(INDENT "HaveFirstKeyboard: %s\n", toString(mHaveFirstKeyboard));
- dump.appendFormat(INDENT "FirstKeyboardId: 0x%x\n", mFirstKeyboardId);
+ dump.appendFormat(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
dump.append(INDENT "Devices:\n");
- for (int i = 0; i < mNumDevicesById; i++) {
- const device_t* device = mDevicesById[i].device;
+ for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
+ const Device* device = mDevices[i];
if (device) {
- if (mFirstKeyboardId == device->id) {
- dump.appendFormat(INDENT2 "0x%x: %s (aka device 0 - first keyboard)\n",
- device->id, device->name.string());
+ if (mBuiltInKeyboardId == device->id) {
+ dump.appendFormat(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
+ device->id, device->identifier.name.string());
} else {
- dump.appendFormat(INDENT2 "0x%x: %s\n", device->id, device->name.string());
+ dump.appendFormat(INDENT2 "%d: %s\n", device->id,
+ device->identifier.name.string());
}
dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
- dump.appendFormat(INDENT3 "IsDefaultKeyMap: %s\n",
- toString(device->keyMapInfo.isDefaultKeyMap));
+ dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
+ dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
+ dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
+ "product=0x%04x, version=0x%04x\n",
+ device->identifier.bus, device->identifier.vendor,
+ device->identifier.product, device->identifier.version);
dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n",
- device->keyMapInfo.keyLayoutFile.string());
+ device->keyMap.keyLayoutFile.string());
dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n",
- device->keyMapInfo.keyCharacterMapFile.string());
+ device->keyMap.keyCharacterMapFile.string());
dump.appendFormat(INDENT3 "ConfigurationFile: %s\n",
device->configurationFile.string());
}
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 9e697db..b8d59e6 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <unistd.h>
+#include <ctype.h>
#include <ui/Input.h>
@@ -28,12 +29,16 @@ static const char* CONFIGURATION_FILE_EXTENSION[] = {
".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 (ch == ' ') {
+ if (!isValidNameChar(ch)) {
ch = '_';
}
path.append(&ch, 1);
@@ -41,7 +46,37 @@ static void appendInputDeviceConfigurationFileRelativePath(String8& path,
path.append(CONFIGURATION_FILE_EXTENSION[type]);
}
-extern String8 getInputDeviceConfigurationFilePath(
+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;
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 0708223..f1223f1 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -315,7 +315,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
// Throttle it!
#if DEBUG_THROTTLING
LOGD("Throttling - Delaying motion event for "
- "device 0x%x, source 0x%08x by up to %0.3fms.",
+ "device %d, source 0x%08x by up to %0.3fms.",
deviceId, source, (nextTime - currentTime) * 0.000001);
#endif
if (nextTime < *nextWakeupTime) {
@@ -704,7 +704,7 @@ bool InputDispatcher::dispatchKeyLocked(
void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
+ LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
"action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
"repeatCount=%d, downTime=%lld",
prefix,
@@ -767,7 +767,7 @@ bool InputDispatcher::dispatchMotionLocked(
void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- LOGD("%seventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
+ LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
"action=0x%x, flags=0x%x, "
"metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
prefix,
@@ -2072,7 +2072,7 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou
uint32_t policyFlags, int32_t action, int32_t flags,
int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
#if DEBUG_INBOUND_EVENT_DETAILS
- LOGD("notifyKey - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
+ LOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
"flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
eventTime, deviceId, source, policyFlags, action, flags,
keyCode, scanCode, metaState, downTime);
@@ -2120,7 +2120,7 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) {
#if DEBUG_INBOUND_EVENT_DETAILS
- LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
+ LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
"action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
"xPrecision=%f, yPrecision=%f, downTime=%lld",
eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index aa690e5..9cc96ad 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -25,6 +25,7 @@
#include <cutils/log.h>
#include <ui/InputReader.h>
#include <ui/Keyboard.h>
+#include <ui/VirtualKeyMap.h>
#include <stddef.h>
#include <stdlib.h>
@@ -121,7 +122,7 @@ void InputReader::loopOnce() {
mEventHub->getEvent(& rawEvent);
#if DEBUG_RAW_EVENTS
- LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
+ LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
rawEvent.value);
#endif
@@ -157,9 +158,9 @@ void InputReader::addDevice(int32_t deviceId) {
device->configure();
if (device->isIgnored()) {
- LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", deviceId, name.string());
+ LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
} else {
- LOGI("Device added: id=0x%x, name=%s, sources=%08x", deviceId, name.string(),
+ LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
device->getSources());
}
@@ -201,10 +202,10 @@ void InputReader::removeDevice(int32_t deviceId) {
}
if (device->isIgnored()) {
- LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)",
+ LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
device->getId(), device->getName().string());
} else {
- LOGI("Device removed: id=0x%x, name=%s, sources=%08x",
+ LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
device->getId(), device->getName().string(), device->getSources());
}
@@ -535,7 +536,7 @@ void InputDevice::dump(String8& dump) {
InputDeviceInfo deviceInfo;
getDeviceInfo(& deviceInfo);
- dump.appendFormat(INDENT "Device 0x%x: %s\n", deviceInfo.getId(),
+ dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
deviceInfo.getName().string());
dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
@@ -1439,7 +1440,7 @@ bool TouchInputMapper::configureSurfaceLocked() {
bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
if (sizeChanged) {
- LOGI("Device reconfigured: id=0x%x, name=%s, display size is now %dx%d",
+ LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
getDeviceId(), getDeviceName().string(), width, height);
mLocked.surfaceWidth = width;
@@ -1651,9 +1652,8 @@ void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
void TouchInputMapper::configureVirtualKeysLocked() {
assert(mRawAxes.x.valid && mRawAxes.y.valid);
- // Note: getVirtualKeyDefinitions is non-reentrant so we can continue holding the lock.
Vector<VirtualKeyDefinition> virtualKeyDefinitions;
- getPolicy()->getVirtualKeyDefinitions(getDeviceName(), virtualKeyDefinitions);
+ getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
mLocked.virtualKeys.clear();
diff --git a/libs/ui/Keyboard.cpp b/libs/ui/Keyboard.cpp
index a4cc22d..6faa600 100644
--- a/libs/ui/Keyboard.cpp
+++ b/libs/ui/Keyboard.cpp
@@ -22,97 +22,167 @@
#include <ui/Keyboard.h>
#include <ui/KeycodeLabels.h>
+#include <ui/KeyLayoutMap.h>
+#include <ui/KeyCharacterMap.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <cutils/properties.h>
namespace android {
-static bool probeKeyMap(KeyMapInfo& keyMapInfo, const String8& keyMapName, bool defaultKeyMap) {
- bool foundOne = false;
- if (keyMapInfo.keyLayoutFile.isEmpty()) {
- keyMapInfo.keyLayoutFile.setTo(getInputDeviceConfigurationFilePath(keyMapName,
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
- if (!keyMapInfo.keyLayoutFile.isEmpty()) {
- foundOne = true;
- }
- }
+// --- KeyMap ---
- if (keyMapInfo.keyCharacterMapFile.isEmpty()) {
- keyMapInfo.keyCharacterMapFile.setTo(getInputDeviceConfigurationFilePath(keyMapName,
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
- if (!keyMapInfo.keyCharacterMapFile.isEmpty()) {
- foundOne = true;
- }
- }
+KeyMap::KeyMap() :
+ keyLayoutMap(NULL), keyCharacterMap(NULL) {
+}
- if (foundOne && defaultKeyMap) {
- keyMapInfo.isDefaultKeyMap = true;
- }
- return keyMapInfo.isComplete();
+KeyMap::~KeyMap() {
+ delete keyLayoutMap;
+ delete keyCharacterMap;
}
-status_t resolveKeyMap(const String8& deviceName,
- const PropertyMap* deviceConfiguration, KeyMapInfo& outKeyMapInfo) {
+status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,
+ const PropertyMap* deviceConfiguration) {
// Use the configured key layout if available.
if (deviceConfiguration) {
String8 keyLayoutName;
if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
keyLayoutName)) {
- outKeyMapInfo.keyLayoutFile.setTo(getInputDeviceConfigurationFilePath(
- keyLayoutName, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
- if (outKeyMapInfo.keyLayoutFile.isEmpty()) {
- LOGW("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
+ status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName);
+ if (status == NAME_NOT_FOUND) {
+ LOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
"it was not found.",
- deviceName.string(), keyLayoutName.string());
+ deviceIdenfifier.name.string(), keyLayoutName.string());
}
}
String8 keyCharacterMapName;
if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
keyCharacterMapName)) {
- outKeyMapInfo.keyCharacterMapFile.setTo(getInputDeviceConfigurationFilePath(
- keyCharacterMapName, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
- if (outKeyMapInfo.keyCharacterMapFile.isEmpty()) {
- LOGW("Configuration for keyboard device '%s' requested keyboard character "
+ status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName);
+ if (status == NAME_NOT_FOUND) {
+ LOGE("Configuration for keyboard device '%s' requested keyboard character "
"map '%s' but it was not found.",
- deviceName.string(), keyCharacterMapName.string());
+ deviceIdenfifier.name.string(), keyLayoutName.string());
}
}
- if (outKeyMapInfo.isComplete()) {
+ if (isComplete()) {
return OK;
}
}
- // Try searching by device name.
- if (probeKeyMap(outKeyMapInfo, deviceName, false)) {
+ // Try searching by device identifier.
+ if (probeKeyMap(deviceIdenfifier, String8::empty())) {
return OK;
}
// Fall back on the Generic key map.
// TODO Apply some additional heuristics here to figure out what kind of
- // generic key map to use (US English, etc.).
- if (probeKeyMap(outKeyMapInfo, String8("Generic"), true)) {
+ // generic key map to use (US English, etc.) for typical external keyboards.
+ if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
+ return OK;
+ }
+
+ // Try the Virtual key map as a last resort.
+ if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {
return OK;
}
// Give up!
- LOGE("Could not determine key map for device '%s' and the Generic key map was not found!",
- deviceName.string());
- outKeyMapInfo.isDefaultKeyMap = true;
+ LOGE("Could not determine key map for device '%s' and no default key maps were found!",
+ deviceIdenfifier.name.string());
return NAME_NOT_FOUND;
}
-void setKeyboardProperties(int32_t deviceId, const String8& deviceName,
- const KeyMapInfo& keyMapInfo) {
+bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
+ const String8& keyMapName) {
+ if (!haveKeyLayout()) {
+ loadKeyLayout(deviceIdentifier, keyMapName);
+ }
+ if (!haveKeyCharacterMap()) {
+ loadKeyCharacterMap(deviceIdentifier, keyMapName);
+ }
+ return isComplete();
+}
+
+status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
+ const String8& name) {
+ String8 path(getPath(deviceIdentifier, name,
+ INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
+ if (path.isEmpty()) {
+ return NAME_NOT_FOUND;
+ }
+
+ KeyLayoutMap* map;
+ status_t status = KeyLayoutMap::load(path, &map);
+ if (status) {
+ return status;
+ }
+
+ keyLayoutFile.setTo(path);
+ keyLayoutMap = map;
+ return OK;
+}
+
+status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
+ const String8& name) {
+ String8 path(getPath(deviceIdentifier, name,
+ INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
+ if (path.isEmpty()) {
+ return NAME_NOT_FOUND;
+ }
+
+ KeyCharacterMap* map;
+ status_t status = KeyCharacterMap::load(path, &map);
+ if (status) {
+ return status;
+ }
+
+ keyCharacterMapFile.setTo(path);
+ keyCharacterMap = map;
+ return OK;
+}
+
+String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
+ const String8& name, InputDeviceConfigurationFileType type) {
+ return name.isEmpty()
+ ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
+ : getInputDeviceConfigurationFilePathByName(name, type);
+}
+
+
+// --- Global functions ---
+
+bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier,
+ const PropertyMap* deviceConfiguration, const KeyMap* keyMap) {
+ if (!keyMap->haveKeyCharacterMap()
+ || keyMap->keyCharacterMap->getKeyboardType()
+ == KeyCharacterMap::KEYBOARD_TYPE_SPECIAL_FUNCTION) {
+ return false;
+ }
+
+ if (deviceConfiguration) {
+ bool builtIn = false;
+ if (deviceConfiguration->tryGetProperty(String8("keyboard.builtIn"), builtIn)
+ && builtIn) {
+ return true;
+ }
+ }
+
+ return strstr(deviceIdentifier.name.string(), "-keypad");
+}
+
+void setKeyboardProperties(int32_t deviceId,
+ const InputDeviceIdentifier& deviceIdentifier,
+ const String8& keyLayoutFile, const String8& keyCharacterMapFile) {
char propName[PROPERTY_KEY_MAX];
snprintf(propName, sizeof(propName), "hw.keyboards.%u.devname", deviceId);
- property_set(propName, deviceName.string());
+ property_set(propName, deviceIdentifier.name.string());
snprintf(propName, sizeof(propName), "hw.keyboards.%u.klfile", deviceId);
- property_set(propName, keyMapInfo.keyLayoutFile.string());
+ property_set(propName, keyLayoutFile.string());
snprintf(propName, sizeof(propName), "hw.keyboards.%u.kcmfile", deviceId);
- property_set(propName, keyMapInfo.keyCharacterMapFile.string());
+ property_set(propName, keyCharacterMapFile.string());
}
void clearKeyboardProperties(int32_t deviceId) {
@@ -126,29 +196,24 @@ void clearKeyboardProperties(int32_t deviceId) {
}
status_t getKeyCharacterMapFile(int32_t deviceId, String8& outKeyCharacterMapFile) {
- if (deviceId == DEVICE_ID_VIRTUAL_KEYBOARD) {
- outKeyCharacterMapFile.setTo(getInputDeviceConfigurationFilePath(String8("Virtual"),
- INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
- if (!outKeyCharacterMapFile.isEmpty()) {
+ if (deviceId != DEVICE_ID_VIRTUAL_KEYBOARD) {
+ char propName[PROPERTY_KEY_MAX];
+ char fn[PROPERTY_VALUE_MAX];
+ snprintf(propName, sizeof(propName), "hw.keyboards.%u.kcmfile", deviceId);
+ if (property_get(propName, fn, "") > 0) {
+ outKeyCharacterMapFile.setTo(fn);
return OK;
}
}
- char propName[PROPERTY_KEY_MAX];
- char fn[PROPERTY_VALUE_MAX];
- snprintf(propName, sizeof(propName), "hw.keyboards.%u.kcmfile", deviceId);
- if (property_get(propName, fn, "") > 0) {
- outKeyCharacterMapFile.setTo(fn);
- return OK;
- }
-
- outKeyCharacterMapFile.setTo(getInputDeviceConfigurationFilePath(String8("Generic"),
+ // Default to Virtual since the keyboard does not appear to be installed.
+ outKeyCharacterMapFile.setTo(getInputDeviceConfigurationFilePathByName(String8("Virtual"),
INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
if (!outKeyCharacterMapFile.isEmpty()) {
return OK;
}
- LOGE("Can't find any key character map files (also tried Virtual and Generic key maps)");
+ LOGE("Can't find any key character map files including the Virtual key map!");
return NAME_NOT_FOUND;
}
diff --git a/libs/ui/VirtualKeyMap.cpp b/libs/ui/VirtualKeyMap.cpp
new file mode 100644
index 0000000..e756cdd
--- /dev/null
+++ b/libs/ui/VirtualKeyMap.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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 "VirtualKeyMap"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ui/VirtualKeyMap.h>
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/Tokenizer.h>
+#include <utils/Timers.h>
+
+// Enables debug output for the parser.
+#define DEBUG_PARSER 0
+
+// Enables debug output for parser performance.
+#define DEBUG_PARSER_PERFORMANCE 0
+
+
+namespace android {
+
+static const char* WHITESPACE = " \t\r";
+static const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:";
+
+
+// --- VirtualKeyMap ---
+
+VirtualKeyMap::VirtualKeyMap() {
+}
+
+VirtualKeyMap::~VirtualKeyMap() {
+}
+
+status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) {
+ *outMap = NULL;
+
+ Tokenizer* tokenizer;
+ status_t status = Tokenizer::open(filename, &tokenizer);
+ if (status) {
+ LOGE("Error %d opening virtual key map file %s.", status, filename.string());
+ } else {
+ VirtualKeyMap* map = new VirtualKeyMap();
+ if (!map) {
+ LOGE("Error allocating virtual key map.");
+ status = NO_MEMORY;
+ } else {
+#if DEBUG_PARSER_PERFORMANCE
+ nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
+#endif
+ Parser parser(map, tokenizer);
+ status = parser.parse();
+#if DEBUG_PARSER_PERFORMANCE
+ nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
+ LOGD("Parsed key character map file '%s' %d lines in %0.3fms.",
+ tokenizer->getFilename().string(), tokenizer->getLineNumber(),
+ elapsedTime / 1000000.0);
+#endif
+ if (status) {
+ delete map;
+ } else {
+ *outMap = map;
+ }
+ }
+ delete tokenizer;
+ }
+ return status;
+}
+
+
+// --- VirtualKeyMap::Parser ---
+
+VirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) :
+ mMap(map), mTokenizer(tokenizer) {
+}
+
+VirtualKeyMap::Parser::~Parser() {
+}
+
+status_t VirtualKeyMap::Parser::parse() {
+ while (!mTokenizer->isEof()) {
+#if DEBUG_PARSER
+ LOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
+ mTokenizer->peekRemainderOfLine().string());
+#endif
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+
+ if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
+ // Multiple keys can appear on one line or they can be broken up across multiple lines.
+ do {
+ String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
+ if (token != "0x01") {
+ LOGE("%s: Unknown virtual key type, expected 0x01.",
+ mTokenizer->getLocation().string());
+ return BAD_VALUE;
+ }
+
+ VirtualKeyDefinition defn;
+ bool success = parseNextIntField(&defn.scanCode)
+ && parseNextIntField(&defn.centerX)
+ && parseNextIntField(&defn.centerY)
+ && parseNextIntField(&defn.width)
+ && parseNextIntField(&defn.height);
+ if (!success) {
+ LOGE("%s: Expected 5 colon-delimited integers in virtual key definition.",
+ mTokenizer->getLocation().string());
+ return BAD_VALUE;
+ }
+
+#if DEBUG_PARSER
+ LOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, "
+ "width=%d, height=%d",
+ defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height);
+#endif
+ mMap->mVirtualKeys.push(defn);
+ } while (consumeFieldDelimiterAndSkipWhitespace());
+
+ if (!mTokenizer->isEol()) {
+ LOGE("%s: Expected end of line, got '%s'.",
+ mTokenizer->getLocation().string(),
+ mTokenizer->peekRemainderOfLine().string());
+ return BAD_VALUE;
+ }
+ }
+
+ mTokenizer->nextLine();
+ }
+
+ return NO_ERROR;
+}
+
+bool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ if (mTokenizer->peekChar() == ':') {
+ mTokenizer->nextChar();
+ mTokenizer->skipDelimiters(WHITESPACE);
+ return true;
+ }
+ return false;
+}
+
+bool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) {
+ if (!consumeFieldDelimiterAndSkipWhitespace()) {
+ return false;
+ }
+
+ String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
+ char* end;
+ *outValue = strtol(token.string(), &end, 0);
+ if (token.isEmpty() || *end != '\0') {
+ LOGE("Expected an integer, got '%s'.", token.string());
+ return false;
+ }
+ return true;
+}
+
+} // namespace android
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
index 05bebc5..d6c2cbd 100644
--- a/libs/ui/tests/InputReader_test.cpp
+++ b/libs/ui/tests/InputReader_test.cpp
@@ -42,7 +42,6 @@ class FakeInputReaderPolicy : public InputReaderPolicyInterface {
KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
bool mFilterTouchEvents;
bool mFilterJumpyTouchEvents;
- KeyedVector<String8, Vector<VirtualKeyDefinition> > mVirtualKeyDefinitions;
Vector<String8> mExcludedDeviceNames;
protected:
@@ -75,15 +74,6 @@ public:
mFilterJumpyTouchEvents = enabled;
}
- void addVirtualKeyDefinition(const String8& deviceName,
- const VirtualKeyDefinition& definition) {
- if (mVirtualKeyDefinitions.indexOfKey(deviceName) < 0) {
- mVirtualKeyDefinitions.add(deviceName, Vector<VirtualKeyDefinition>());
- }
-
- mVirtualKeyDefinitions.editValueFor(deviceName).push(definition);
- }
-
void addExcludedDeviceName(const String8& deviceName) {
mExcludedDeviceNames.push(deviceName);
}
@@ -116,14 +106,6 @@ private:
return mFilterJumpyTouchEvents;
}
- virtual void getVirtualKeyDefinitions(const String8& deviceName,
- Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) {
- ssize_t index = mVirtualKeyDefinitions.indexOfKey(deviceName);
- if (index >= 0) {
- outVirtualKeyDefinitions.appendVector(mVirtualKeyDefinitions.valueAt(index));
- }
- }
-
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
outExcludedDeviceNames.appendVector(mExcludedDeviceNames);
}
@@ -355,6 +337,7 @@ class FakeEventHub : public EventHubInterface {
KeyedVector<int32_t, int32_t> switchStates;
KeyedVector<int32_t, KeyInfo> keys;
KeyedVector<int32_t, bool> leds;
+ Vector<VirtualKeyDefinition> virtualKeys;
Device(const String8& name, uint32_t classes) :
name(name), classes(classes) {
@@ -448,6 +431,11 @@ public:
return mExcludedDevices;
}
+ void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
+ Device* device = getDevice(deviceId);
+ device->virtualKeys.push(definition);
+ }
+
void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type,
int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
RawEvent event;
@@ -603,6 +591,16 @@ private:
}
}
+ virtual void getVirtualKeyDefinitions(int32_t deviceId,
+ Vector<VirtualKeyDefinition>& outVirtualKeys) const {
+ outVirtualKeys.clear();
+
+ Device* device = getDevice(deviceId);
+ if (device) {
+ outVirtualKeys.appendVector(device->virtualKeys);
+ }
+ }
+
virtual void dump(String8& dump) {
}
};
@@ -2147,8 +2145,8 @@ void TouchInputMapperTest::prepareDisplay(int32_t orientation) {
}
void TouchInputMapperTest::prepareVirtualKeys() {
- mFakePolicy->addVirtualKeyDefinition(String8(DEVICE_NAME), VIRTUAL_KEYS[0]);
- mFakePolicy->addVirtualKeyDefinition(String8(DEVICE_NAME), VIRTUAL_KEYS[1]);
+ mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]);
+ mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]);
mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, AKEYCODE_MENU, POLICY_FLAG_WAKE);
}
diff --git a/libs/utils/FileMap.cpp b/libs/utils/FileMap.cpp
index e1ba9b2..f1f8bda 100644
--- a/libs/utils/FileMap.cpp
+++ b/libs/utils/FileMap.cpp
@@ -63,16 +63,18 @@ FileMap::~FileMap(void)
free(mFileName);
}
#ifdef HAVE_POSIX_FILEMAP
- if (munmap(mBasePtr, mBaseLength) != 0) {
+ if (mBasePtr && munmap(mBasePtr, mBaseLength) != 0) {
LOGD("munmap(%p, %d) failed\n", mBasePtr, (int) mBaseLength);
}
#endif
#ifdef HAVE_WIN32_FILEMAP
- if ( UnmapViewOfFile(mBasePtr) == 0) {
+ if (mBasePtr && UnmapViewOfFile(mBasePtr) == 0) {
LOGD("UnmapViewOfFile(%p) failed, error = %ld\n", mBasePtr,
GetLastError() );
}
- CloseHandle(mFileMapping);
+ if (mFileMapping != INVALID_HANDLE_VALUE) {
+ CloseHandle(mFileMapping);
+ }
CloseHandle(mFileHandle);
#endif
}
diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp
index e531a2a..0bc5aff 100644
--- a/libs/utils/String8.cpp
+++ b/libs/utils/String8.cpp
@@ -195,6 +195,24 @@ String8::~String8()
SharedBuffer::bufferFromData(mString)->release();
}
+String8 String8::format(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ String8 result(formatV(fmt, args));
+
+ va_end(args);
+ return result;
+}
+
+String8 String8::formatV(const char* fmt, va_list args)
+{
+ String8 result;
+ result.appendFormatV(fmt, args);
+ return result;
+}
+
void String8::clear() {
SharedBuffer::bufferFromData(mString)->release();
mString = getEmptyString();
diff --git a/libs/utils/Tokenizer.cpp b/libs/utils/Tokenizer.cpp
index 9251973..b3445b7 100644
--- a/libs/utils/Tokenizer.cpp
+++ b/libs/utils/Tokenizer.cpp
@@ -35,16 +35,16 @@ static inline bool isDelimiter(char ch, const char* delimiters) {
return strchr(delimiters, ch) != NULL;
}
-
-Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap,
- const char* buffer, size_t length) :
- mFilename(filename), mFileMap(fileMap), mBuffer(buffer), mLength(length),
- mCurrent(buffer), mLineNumber(1) {
+Tokenizer::Tokenizer(const String8& filename, FileMap* fileMap, char* buffer, size_t length) :
+ mFilename(filename), mFileMap(fileMap),
+ mBuffer(buffer), mLength(length), mCurrent(buffer), mLineNumber(1) {
}
Tokenizer::~Tokenizer() {
if (mFileMap) {
mFileMap->release();
+ } else {
+ delete[] mBuffer;
}
}
@@ -63,22 +63,33 @@ status_t Tokenizer::open(const String8& filename, Tokenizer** outTokenizer) {
LOGE("Error getting size of file '%s', %s.", filename.string(), strerror(errno));
} else {
size_t length = size_t(stat.st_size);
+
FileMap* fileMap = new FileMap();
- if (!fileMap->create(NULL, fd, 0, length, true)) {
- result = NO_MEMORY;
- LOGE("Error mapping file '%s', %s.", filename.string(), strerror(errno));
- } else {
+ char* buffer;
+ if (fileMap->create(NULL, fd, 0, length, true)) {
fileMap->advise(FileMap::SEQUENTIAL);
-
- *outTokenizer = new Tokenizer(filename, fileMap,
- static_cast<const char*>(fileMap->getDataPtr()), length);
- if (!*outTokenizer) {
- result = NO_MEMORY;
- LOGE("Error allocating tokenizer for file=%s.", filename.string());
+ buffer = static_cast<char*>(fileMap->getDataPtr());
+ } else {
+ fileMap->release();
+ fileMap = NULL;
+
+ // Fall back to reading into a buffer since we can't mmap files in sysfs.
+ // The length we obtained from stat is wrong too (it will always be 4096)
+ // so we must trust that read will read the entire file.
+ buffer = new char[length];
+ ssize_t nrd = read(fd, buffer, length);
+ if (nrd < 0) {
+ result = -errno;
+ LOGE("Error reading file '%s', %s.", filename.string(), strerror(errno));
+ delete[] buffer;
+ buffer = NULL;
+ } else {
+ length = size_t(nrd);
}
}
- if (result) {
- fileMap->release();
+
+ if (!result) {
+ *outTokenizer = new Tokenizer(filename, fileMap, buffer, length);
}
}
close(fd);
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 0e689e4..beac04c 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -194,6 +194,7 @@ public class MediaFile {
addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp");
addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl", MtpConstants.FORMAT_M3U_PLAYLIST);
+ addFileType("M3U", FILE_TYPE_M3U, "application/x-mpegurl", MtpConstants.FORMAT_M3U_PLAYLIST);
addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls", MtpConstants.FORMAT_PLS_PLAYLIST);
addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl", MtpConstants.FORMAT_WPL_PLAYLIST);
addFileType("M3U8", FILE_TYPE_HTTPLIVE, "application/vnd.apple.mpegurl");
diff --git a/media/java/android/media/videoeditor/VideoEditor.java b/media/java/android/media/videoeditor/VideoEditor.java
index 64d3229..37bb661 100755
--- a/media/java/android/media/videoeditor/VideoEditor.java
+++ b/media/java/android/media/videoeditor/VideoEditor.java
@@ -98,6 +98,31 @@ public interface VideoEditor {
}
/**
+ * This listener interface is used by the VideoEditor to emit export status
+ * notifications.
+ * {@link #generatePreview(MediaProcessingProgressListener listener)}
+ */
+ public interface MediaProcessingProgressListener {
+ // Values used for the action parameter
+ public static final int ACTION_ENCODE = 1;
+ public static final int ACTION_DECODE = 2;
+
+ /**
+ * This method notifies the listener of the progress status of
+ * processing a media object such as a Transition, AudioTrack or a
+ * media image item (when Ken Burns effect is applied).
+ * This method may be called maximum 100 times for one operation.
+ *
+ * @param object The object that is being processed such as a
+ * Transition or AudioTrack
+ * @param action The type of processing being performed
+ * @param progress The progress in %. At the beginning of the operation,
+ * this value is set to 0; at the end, the value is set to 100.
+ */
+ public void onProgress(Object item, int action, int progress);
+ }
+
+ /**
* @return The path where the VideoEditor stores all files related to the
* project
*/
@@ -496,8 +521,11 @@ public interface VideoEditor {
* This method must be called after the aspect ratio of the project changes
* and before startPreview is called. Note that this method may block for
* an extensive period of time.
+ *
+ * @param listener The listener interface which will be used to notify
+ * the caller of the progress of each storyboard item being processed.
*/
- public void generatePreview();
+ public void generatePreview(MediaProcessingProgressListener listener);
/**
* Start the preview of all the storyboard items applied on all MediaItems
diff --git a/media/java/android/media/videoeditor/VideoEditorFactory.java b/media/java/android/media/videoeditor/VideoEditorFactory.java
index 41eed16..85b2666 100755
--- a/media/java/android/media/videoeditor/VideoEditorFactory.java
+++ b/media/java/android/media/videoeditor/VideoEditorFactory.java
@@ -19,8 +19,8 @@ package android.media.videoeditor;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
+
+import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
/**
@@ -30,34 +30,19 @@ import java.lang.reflect.InvocationTargetException;
* {@hide}
*/
public class VideoEditorFactory {
- // VideoEditor implementation classes
- public static final String TEST_CLASS_IMPLEMENTATION
- = "android.media.videoeditor.VideoEditorTestImpl";
- public static final String DEFAULT_CLASS_IMPLEMENTATION
- = "android.media.videoeditor.VideoEditorImpl";
-
/**
* This is the factory method for creating a new VideoEditor instance.
*
* @param projectPath The path where all VideoEditor internal
* files are stored. When a project is deleted the application is
* responsible for deleting the path and its contents.
- * @param className The implementation class name
*
* @return The VideoEditor instance
*
* @throws IOException if path does not exist or if the path can
* not be accessed in read/write mode
- * @throws IllegalStateException if a previous VideoEditor instance has not
- * been released
- * @throws ClassNotFoundException, NoSuchMethodException,
- * InvocationTargetException, IllegalAccessException,
- * InstantiationException if the implementation class cannot
- * be instantiated.
*/
- public static VideoEditor create(String projectPath, String className) throws IOException,
- ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
- IllegalAccessException, InstantiationException {
+ public static VideoEditor create(String projectPath) throws IOException {
// If the project path does not exist create it
final File dir = new File(projectPath);
if (!dir.exists()) {
@@ -72,14 +57,7 @@ public class VideoEditorFactory {
}
}
- final Class<?> cls = Class.forName(className);
- final Class<?> partypes[] = new Class[1];
- partypes[0] = String.class;
- final Constructor<?> ct = cls.getConstructor(partypes);
- final Object arglist[] = new Object[1];
- arglist[0] = projectPath;
-
- return (VideoEditor)ct.newInstance(arglist);
+ return new VideoEditorImpl(projectPath);
}
/**
@@ -90,32 +68,21 @@ public class VideoEditorFactory {
* @param projectPath The path where all VideoEditor internal files
* are stored. When a project is deleted the application is
* responsible for deleting the path and its contents.
- * @param className The implementation class name
* @param generatePreview if set to true the
- * {@link MediaEditor#generatePreview()} will be called internally to
- * generate any needed transitions.
+ * {@link MediaEditor#generatePreview(MediaProcessingProgressListener listener)}
+ * will be called internally to generate any needed transitions.
*
* @return The VideoEditor instance
*
* @throws IOException if path does not exist or if the path can
* not be accessed in read/write mode or if one of the resource
* media files cannot be retrieved
- * @throws IllegalStateException if a previous VideoEditor instance has not
- * been released
*/
- public static VideoEditor load(String projectPath, String className, boolean generatePreview)
- throws IOException, ClassNotFoundException, NoSuchMethodException,
- InvocationTargetException, IllegalAccessException, InstantiationException {
- final Class<?> cls = Class.forName(className);
- final Class<?> partypes[] = new Class[1];
- partypes[0] = String.class;
- final Constructor<?> ct = cls.getConstructor(partypes);
- final Object arglist[] = new Object[1];
- arglist[0] = projectPath;
-
- final VideoEditor videoEditor = (VideoEditor)ct.newInstance(arglist);
+ public static VideoEditor load(String projectPath, boolean generatePreview)
+ throws IOException {
+ final VideoEditor videoEditor = new VideoEditorImpl(projectPath);
if (generatePreview) {
- videoEditor.generatePreview();
+ videoEditor.generatePreview(null);
}
return videoEditor;
}
diff --git a/media/java/android/media/videoeditor/VideoEditorTestImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index ca896c3..1a145e6 100644
--- a/media/java/android/media/videoeditor/VideoEditorTestImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -39,7 +39,7 @@ import android.view.SurfaceHolder;
/**
* The VideoEditor implementation {@hide}
*/
-public class VideoEditorTestImpl implements VideoEditor {
+public class VideoEditorImpl implements VideoEditor {
// Logging
private static final String TAG = "VideoEditorImpl";
@@ -165,7 +165,7 @@ public class VideoEditorTestImpl implements VideoEditor {
if (mPositionMs >= mToMs) {
if (!mLoop) {
if (mListener != null) {
- mListener.onProgress(VideoEditorTestImpl.this, mPositionMs, true);
+ mListener.onProgress(VideoEditorImpl.this, mPositionMs, true);
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "PreviewThread.run playback complete");
@@ -174,13 +174,13 @@ public class VideoEditorTestImpl implements VideoEditor {
} else {
// Fire a notification for the end of the clip
if (mListener != null) {
- mListener.onProgress(VideoEditorTestImpl.this, mToMs, false);
+ mListener.onProgress(VideoEditorImpl.this, mToMs, false);
}
// Rewind
mPositionMs = mFromMs;
if (mListener != null) {
- mListener.onProgress(VideoEditorTestImpl.this, mPositionMs, false);
+ mListener.onProgress(VideoEditorImpl.this, mPositionMs, false);
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "PreviewThread.run playback complete");
@@ -190,7 +190,7 @@ public class VideoEditorTestImpl implements VideoEditor {
} else {
if (frameCount == mCallbackAfterFrameCount) {
if (mListener != null) {
- mListener.onProgress(VideoEditorTestImpl.this, mPositionMs, false);
+ mListener.onProgress(VideoEditorImpl.this, mPositionMs, false);
}
frameCount = 0;
}
@@ -222,7 +222,7 @@ public class VideoEditorTestImpl implements VideoEditor {
*
* @param projectPath
*/
- public VideoEditorTestImpl(String projectPath) throws IOException {
+ public VideoEditorImpl(String projectPath) throws IOException {
mProjectPath = projectPath;
final File projectXml = new File(projectPath, PROJECT_FILENAME);
if (projectXml.exists()) {
@@ -1055,7 +1055,7 @@ public class VideoEditorTestImpl implements VideoEditor {
/*
* {@inheritDoc}
*/
- public void generatePreview() {
+ public void generatePreview(MediaProcessingProgressListener listener) {
// Generate all the needed transitions
for (Transition transition : mTransitions) {
if (!transition.isGenerated()) {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index d2dbf0d..cee92d2 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1164,8 +1164,11 @@ status_t StagefrightRecorder::setupVideoEncoder(
CHECK_EQ(client.connect(), OK);
// Use software codec for time lapse
- uint32_t encoder_flags = (mCaptureTimeLapse) ? OMXCodec::kPreferSoftwareCodecs : 0;
- if (mIsMetaDataStoredInVideoBuffers) {
+ uint32_t encoder_flags = 0;
+ if (mCaptureTimeLapse) {
+ encoder_flags |= OMXCodec::kPreferSoftwareCodecs;
+ } else if (mIsMetaDataStoredInVideoBuffers) {
+ encoder_flags |= OMXCodec::kHardwareCodecsOnly;
encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
}
sp<MediaSource> encoder = OMXCodec::Create(
@@ -1173,6 +1176,11 @@ status_t StagefrightRecorder::setupVideoEncoder(
true /* createEncoder */, cameraSource,
NULL, encoder_flags);
if (encoder == NULL) {
+ LOGW("Failed to create the encoder");
+ // When the encoder fails to be created, we need
+ // release the camera source due to the camera's lock
+ // and unlock mechanism.
+ cameraSource->stop();
return UNKNOWN_ERROR;
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index a804866..8ebbe6c 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -426,7 +426,8 @@ status_t AwesomePlayer::setDataSource_l(
// Hack to support http live.
size_t len = strlen(uri);
- if (!strcasecmp(&uri[len - 5], ".m3u8")) {
+ if (!strcasecmp(&uri[len - 5], ".m3u8")
+ || strstr(&uri[7], "m3u8") != NULL) {
mUri = "httplive://";
mUri.append(&uri[7]);
}
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
index e6a0976..e3292e6 100644
--- a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -178,7 +178,7 @@ AVCEncoder::AVCEncoder(
mInputFrameData(NULL),
mGroup(NULL) {
- LOGV("Construct software AVCEncoder");
+ LOGI("Construct software AVCEncoder");
mHandle = new tagAVCHandle;
memset(mHandle, 0, sizeof(tagAVCHandle));
diff --git a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
index c7a475b..15ed219 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -178,7 +178,7 @@ M4vH263Encoder::M4vH263Encoder(
mInputFrameData(NULL),
mGroup(NULL) {
- LOGV("Construct software M4vH263Encoder");
+ LOGI("Construct software M4vH263Encoder");
mHandle = new tagvideoEncControls;
memset(mHandle, 0, sizeof(tagvideoEncControls));
diff --git a/media/libstagefright/httplive/LiveSource.cpp b/media/libstagefright/httplive/LiveSource.cpp
index 4b4c3d2..4451bd5 100644
--- a/media/libstagefright/httplive/LiveSource.cpp
+++ b/media/libstagefright/httplive/LiveSource.cpp
@@ -359,14 +359,6 @@ bool LiveSource::setupCipher() {
return false;
}
- if (keyURI.size() >= 2
- && keyURI.c_str()[0] == '"'
- && keyURI.c_str()[keyURI.size() - 1] == '"') {
- // Remove surrounding quotes.
- AString tmp(keyURI, 1, keyURI.size() - 2);
- keyURI = tmp;
- }
-
ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
sp<ABuffer> key;
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index b166cc3..d4a29c0 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -162,7 +162,7 @@ status_t M3UParser::parse(const void *_data, size_t size) {
if (mIsVariantPlaylist) {
return ERROR_MALFORMED;
}
- err = parseCipherInfo(line, &itemMeta);
+ err = parseCipherInfo(line, &itemMeta, mBaseURI);
} else if (line.startsWith("#EXT-X-ENDLIST")) {
mIsComplete = true;
} else if (line.startsWith("#EXTINF")) {
@@ -298,7 +298,7 @@ status_t M3UParser::parseStreamInf(
// static
status_t M3UParser::parseCipherInfo(
- const AString &line, sp<AMessage> *meta) {
+ const AString &line, sp<AMessage> *meta, const AString &baseURI) {
ssize_t colonPos = line.find(":");
if (colonPos < 0) {
@@ -338,6 +338,24 @@ status_t M3UParser::parseCipherInfo(
*meta = new AMessage;
}
+ if (key == "uri") {
+ if (val.size() >= 2
+ && val.c_str()[0] == '"'
+ && val.c_str()[val.size() - 1] == '"') {
+ // Remove surrounding quotes.
+ AString tmp(val, 1, val.size() - 2);
+ val = tmp;
+ }
+
+ AString absURI;
+ if (MakeURL(baseURI.c_str(), val.c_str(), &absURI)) {
+ val = absURI;
+ } else {
+ LOGE("failed to make absolute url for '%s'.",
+ val.c_str());
+ }
+ }
+
key.insert(AString("cipher-"), 0);
(*meta)->setString(key.c_str(), val.c_str(), val.size());
diff --git a/media/libstagefright/include/M3UParser.h b/media/libstagefright/include/M3UParser.h
index 531d184..63895b4 100644
--- a/media/libstagefright/include/M3UParser.h
+++ b/media/libstagefright/include/M3UParser.h
@@ -67,7 +67,7 @@ private:
const AString &line, sp<AMessage> *meta);
static status_t parseCipherInfo(
- const AString &line, sp<AMessage> *meta);
+ const AString &line, sp<AMessage> *meta, const AString &baseURI);
static status_t ParseInt32(const char *s, int32_t *x);
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index f06a1bb..a559b21 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -238,10 +238,15 @@ void ATSParser::Program::parseProgramMap(ABitReader *br) {
}
sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
+ size_t index = (type == MPEG2ADTS_AUDIO) ? 0 : 0;
+
for (size_t i = 0; i < mStreams.size(); ++i) {
sp<MediaSource> source = mStreams.editValueAt(i)->getSource(type);
if (source != NULL) {
- return source;
+ if (index == 0) {
+ return source;
+ }
+ --index;
}
}
@@ -508,7 +513,10 @@ void ATSParser::Stream::onPayloadData(
int64_t timeUs = mProgram->convertPTSToTimestamp(PTS);
status_t err = mQueue.appendData(data, size, timeUs);
- CHECK_EQ(err, (status_t)OK);
+
+ if (err != OK) {
+ return;
+ }
sp<ABuffer> accessUnit;
while ((accessUnit = mQueue.dequeueAccessUnit()) != NULL) {
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index f11b3c3..37bcb23 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -55,9 +55,34 @@ status_t ElementaryStreamQueue::appendData(
switch (mMode) {
case H264:
{
+#if 0
if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
return ERROR_MALFORMED;
}
+#else
+ uint8_t *ptr = (uint8_t *)data;
+
+ ssize_t startOffset = -1;
+ for (size_t i = 0; i + 3 < size; ++i) {
+ if (!memcmp("\x00\x00\x00\x01", &ptr[i], 4)) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (startOffset > 0) {
+ LOGI("found something resembling an H.264 syncword at "
+ "offset %ld",
+ startOffset);
+ }
+
+ data = &ptr[startOffset];
+ size -= startOffset;
+#endif
break;
}
@@ -65,9 +90,31 @@ status_t ElementaryStreamQueue::appendData(
{
uint8_t *ptr = (uint8_t *)data;
+#if 0
if (size < 2 || ptr[0] != 0xff || (ptr[1] >> 4) != 0x0f) {
return ERROR_MALFORMED;
}
+#else
+ ssize_t startOffset = -1;
+ for (size_t i = 0; i + 1 < size; ++i) {
+ if (ptr[i] == 0xff && (ptr[i + 1] >> 4) == 0x0f) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (startOffset > 0) {
+ LOGI("found something resembling an AAC syncword at offset %ld",
+ startOffset);
+ }
+
+ data = &ptr[startOffset];
+ size -= startOffset;
+#endif
break;
}
diff --git a/packages/DefaultContainerService/res/values-id/strings.xml b/packages/DefaultContainerService/res/values-in/strings.xml
index 2f830b1..2f830b1 100644
--- a/packages/DefaultContainerService/res/values-id/strings.xml
+++ b/packages/DefaultContainerService/res/values-in/strings.xml
diff --git a/packages/DefaultContainerService/res/values-he/strings.xml b/packages/DefaultContainerService/res/values-iw/strings.xml
index ede8178..ede8178 100644
--- a/packages/DefaultContainerService/res/values-he/strings.xml
+++ b/packages/DefaultContainerService/res/values-iw/strings.xml
diff --git a/packages/SettingsProvider/res/values-id/strings.xml b/packages/SettingsProvider/res/values-in/strings.xml
index bed20eb..bed20eb 100644
--- a/packages/SettingsProvider/res/values-id/strings.xml
+++ b/packages/SettingsProvider/res/values-in/strings.xml
diff --git a/packages/SettingsProvider/res/values-he/strings.xml b/packages/SettingsProvider/res/values-iw/strings.xml
index ad2eaf4..ad2eaf4 100644
--- a/packages/SettingsProvider/res/values-he/strings.xml
+++ b/packages/SettingsProvider/res/values-iw/strings.xml
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
index 615c8b6..25fffd6 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
index 0122025..b6e4ebc 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png
index 0786916..189a089 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png
index 35f9240..ebade92 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
index 3eb22df..6ef71c7 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png
index 1ce9bd1..f6b0a17 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
index fef2cf9..91bc4ee 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png
index 05593bc..aa64de4 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
index 32c2c79..246c6fe 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png
index 142c413..34515c7 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/values-id/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 974498a..974498a 100644
--- a/packages/SystemUI/res/values-id/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
diff --git a/packages/SystemUI/res/values-he/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ad1f755..ad1f755 100644
--- a/packages/SystemUI/res/values-he/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
diff --git a/packages/VpnServices/res/values-id/strings.xml b/packages/VpnServices/res/values-in/strings.xml
index 8b6b4c2..8b6b4c2 100644
--- a/packages/VpnServices/res/values-id/strings.xml
+++ b/packages/VpnServices/res/values-in/strings.xml
diff --git a/packages/VpnServices/res/values-he/strings.xml b/packages/VpnServices/res/values-iw/strings.xml
index 74971d6..74971d6 100644
--- a/packages/VpnServices/res/values-he/strings.xml
+++ b/packages/VpnServices/res/values-iw/strings.xml
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 138dff7..b487d92 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -867,7 +867,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (panel.isOpen) {
// The window manager will give us a valid window token
new MenuDialogHelper(subMenu).show(null);
- } else {
+ } else if (hasFeature(FEATURE_ACTION_BAR)) {
mActionButtonPopup = new ActionButtonSubmenu(getContext(), subMenu);
mActionButtonPopup.show();
Callback cb = getCallback();
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 5c67da7..b5e3888 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -430,6 +430,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
mSettingsObserver.observe(mContext);
+
+ loadGlobalProxy();
}
@@ -2089,7 +2091,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
ContentResolver res = mContext.getContentResolver();
Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
- Settings.Secure.putString(res,Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+ Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
exclList);
}
@@ -2099,6 +2101,20 @@ public class ConnectivityService extends IConnectivityManager.Stub {
sendProxyBroadcast(proxyProperties);
}
+ private void loadGlobalProxy() {
+ ContentResolver res = mContext.getContentResolver();
+ String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST);
+ int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0);
+ String exclList = Settings.Secure.getString(res,
+ Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
+ if (!TextUtils.isEmpty(host)) {
+ ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList);
+ synchronized (mGlobalProxyLock) {
+ mGlobalProxy = proxyProperties;
+ }
+ }
+ }
+
public ProxyProperties getGlobalProxy() {
synchronized (mGlobalProxyLock) {
return mGlobalProxy;
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 9078811..8634eec 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -358,16 +358,6 @@ public class InputManager {
}
}
- private static final class VirtualKeyDefinition {
- public int scanCode;
-
- // configured position data, specified in display coords
- public int centerX;
- public int centerY;
- public int width;
- public int height;
- }
-
/*
* Callbacks from native.
*/
@@ -438,54 +428,6 @@ public class InputManager {
}
@SuppressWarnings("unused")
- public VirtualKeyDefinition[] getVirtualKeyDefinitions(String deviceName) {
- ArrayList<VirtualKeyDefinition> keys = new ArrayList<VirtualKeyDefinition>();
-
- try {
- FileInputStream fis = new FileInputStream(
- "/sys/board_properties/virtualkeys." + deviceName);
- InputStreamReader isr = new InputStreamReader(fis);
- BufferedReader br = new BufferedReader(isr, 2048);
- String str = br.readLine();
- if (str != null) {
- String[] it = str.split(":");
- if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "***** VIRTUAL KEYS: " + it);
- final int N = it.length-6;
- for (int i=0; i<=N; i+=6) {
- if (!"0x01".equals(it[i])) {
- Slog.w(TAG, "Unknown virtual key type at elem #"
- + i + ": " + it[i] + " for device " + deviceName);
- continue;
- }
- try {
- VirtualKeyDefinition key = new VirtualKeyDefinition();
- key.scanCode = Integer.parseInt(it[i+1]);
- key.centerX = Integer.parseInt(it[i+2]);
- key.centerY = Integer.parseInt(it[i+3]);
- key.width = Integer.parseInt(it[i+4]);
- key.height = Integer.parseInt(it[i+5]);
- if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Virtual key "
- + key.scanCode + ": center=" + key.centerX + ","
- + key.centerY + " size=" + key.width + "x"
- + key.height);
- keys.add(key);
- } catch (NumberFormatException e) {
- Slog.w(TAG, "Bad number in virtual key definition at region "
- + i + " in: " + str + " for device " + deviceName, e);
- }
- }
- }
- br.close();
- } catch (FileNotFoundException e) {
- Slog.i(TAG, "No virtual keys found for device " + deviceName + ".");
- } catch (IOException e) {
- Slog.w(TAG, "Error reading virtual keys for device " + deviceName + ".", e);
- }
-
- return keys.toArray(new VirtualKeyDefinition[keys.size()]);
- }
-
- @SuppressWarnings("unused")
public String[] getExcludedDeviceNames() {
ArrayList<String> names = new ArrayList<String>();
diff --git a/services/java/com/android/server/SamplingProfilerService.java b/services/java/com/android/server/SamplingProfilerService.java
index 26af7f7..61267d0 100644
--- a/services/java/com/android/server/SamplingProfilerService.java
+++ b/services/java/com/android/server/SamplingProfilerService.java
@@ -88,7 +88,7 @@ public class SamplingProfilerService extends Binder {
private void registerSettingObserver(Context context) {
ContentResolver contentResolver = context.getContentResolver();
contentResolver.registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.SAMPLING_PROFILER_HZ),
+ Settings.Secure.getUriFor(Settings.Secure.SAMPLING_PROFILER_MS),
false, new SamplingProfilerSettingsObserver(contentResolver));
}
@@ -107,12 +107,11 @@ public class SamplingProfilerService extends Binder {
}
@Override
public void onChange(boolean selfChange) {
- Integer samplingProfilerHz = Settings.Secure.getInt(
- mContentResolver, Settings.Secure.SAMPLING_PROFILER_HZ, 0);
+ Integer samplingProfilerMs = Settings.Secure.getInt(
+ mContentResolver, Settings.Secure.SAMPLING_PROFILER_MS, 0);
// setting this secure property will start or stop sampling profiler,
- // as well as adjust the frequency of taking snapshots.
- SystemProperties.set("persist.sys.profiler_hz", samplingProfilerHz.toString());
+ // as well as adjust the the time between taking snapshots.
+ SystemProperties.set("persist.sys.profiler_ms", samplingProfilerMs.toString());
}
}
}
-
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index d7a6a0e..7504bb4 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -6005,6 +6005,7 @@ public class WindowManagerService extends IWindowManager.Stub
int deviceId = ev.getDeviceId();
int scancode = ev.getScanCode();
int source = ev.getSource();
+ int flags = ev.getFlags();
if (source == InputDevice.SOURCE_UNKNOWN) {
source = InputDevice.SOURCE_KEYBOARD;
@@ -6014,7 +6015,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (downTime == 0) downTime = eventTime;
KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
- deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM, source);
+ deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index aa84db5..1996dd0 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -56,7 +56,6 @@ static struct {
jmethodID checkInjectEventsPermission;
jmethodID filterTouchEvents;
jmethodID filterJumpyTouchEvents;
- jmethodID getVirtualKeyDefinitions;
jmethodID getExcludedDeviceNames;
jmethodID getMaxEventsPerSecond;
} gCallbacksClassInfo;
@@ -64,16 +63,6 @@ static struct {
static struct {
jclass clazz;
- jfieldID scanCode;
- jfieldID centerX;
- jfieldID centerY;
- jfieldID width;
- jfieldID height;
-} gVirtualKeyDefinitionClassInfo;
-
-static struct {
- jclass clazz;
-
jfieldID inputChannel;
jfieldID name;
jfieldID layoutParamsFlags;
@@ -176,8 +165,6 @@ public:
int32_t* width, int32_t* height, int32_t* orientation);
virtual bool filterTouchEvents();
virtual bool filterJumpyTouchEvents();
- virtual void getVirtualKeyDefinitions(const String8& deviceName,
- Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions);
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
/* --- InputDispatcherPolicyInterface implementation --- */
@@ -442,41 +429,6 @@ bool NativeInputManager::filterJumpyTouchEvents() {
return mFilterJumpyTouchEvents;
}
-void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
- Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) {
- outVirtualKeyDefinitions.clear();
-
- JNIEnv* env = jniEnv();
-
- jstring deviceNameStr = env->NewStringUTF(deviceName.string());
- if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions")) {
- jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
- gCallbacksClassInfo.getVirtualKeyDefinitions, deviceNameStr));
- if (! checkAndClearExceptionFromCallback(env, "getVirtualKeyDefinitions") && result) {
- jsize length = env->GetArrayLength(result);
- for (jsize i = 0; i < length; i++) {
- jobject item = env->GetObjectArrayElement(result, i);
-
- outVirtualKeyDefinitions.add();
- outVirtualKeyDefinitions.editTop().scanCode =
- int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.scanCode));
- outVirtualKeyDefinitions.editTop().centerX =
- int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerX));
- outVirtualKeyDefinitions.editTop().centerY =
- int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.centerY));
- outVirtualKeyDefinitions.editTop().width =
- int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.width));
- outVirtualKeyDefinitions.editTop().height =
- int32_t(env->GetIntField(item, gVirtualKeyDefinitionClassInfo.height));
-
- env->DeleteLocalRef(item);
- }
- env->DeleteLocalRef(result);
- }
- env->DeleteLocalRef(deviceNameStr);
- }
-}
-
void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
outExcludedDeviceNames.clear();
@@ -1366,36 +1318,12 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz,
"filterJumpyTouchEvents", "()Z");
- GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz,
- "getVirtualKeyDefinitions",
- "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
-
GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
"getExcludedDeviceNames", "()[Ljava/lang/String;");
GET_METHOD_ID(gCallbacksClassInfo.getMaxEventsPerSecond, gCallbacksClassInfo.clazz,
"getMaxEventsPerSecond", "()I");
- // VirtualKeyDefinition
-
- FIND_CLASS(gVirtualKeyDefinitionClassInfo.clazz,
- "com/android/server/InputManager$VirtualKeyDefinition");
-
- GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.scanCode, gVirtualKeyDefinitionClassInfo.clazz,
- "scanCode", "I");
-
- GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerX, gVirtualKeyDefinitionClassInfo.clazz,
- "centerX", "I");
-
- GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.centerY, gVirtualKeyDefinitionClassInfo.clazz,
- "centerY", "I");
-
- GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.width, gVirtualKeyDefinitionClassInfo.clazz,
- "width", "I");
-
- GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
- "height", "I");
-
// InputWindow
FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index b901e0d..bc6ad64 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -92,13 +92,6 @@ public class Canvas_Delegate {
return mGraphicsStack.peek();
}
- /**
- * Disposes of the {@link Graphics2D} stack.
- */
- public void dispose() {
-
- }
-
// ---- native methods ----
/*package*/ static boolean isOpaque(Canvas thisCanvas) {
@@ -985,6 +978,16 @@ public class Canvas_Delegate {
}
/*package*/ static void finalizer(int nativeCanvas) {
+ // get the delegate from the native int so that it can be disposed.
+ Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
+ if (canvasDelegate == null) {
+ assert false;
+ return;
+ }
+
+ canvasDelegate.dispose();
+
+ // remove it from the manager.
sManager.removeDelegate(nativeCanvas);
}
@@ -997,6 +1000,15 @@ public class Canvas_Delegate {
private Canvas_Delegate() {
}
+ /**
+ * Disposes of the {@link Graphics2D} stack.
+ */
+ private void dispose() {
+ while (mGraphicsStack.size() > 0) {
+ mGraphicsStack.pop().dispose();
+ }
+ }
+
private void setBitmap(BufferedImage image) {
mBufferedImage = image;
mGraphicsStack.push(mBufferedImage.createGraphics());
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index ca87b4e..59fcc52 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -33,6 +33,7 @@ import com.android.tools.layoutlib.create.OverrideMethod;
import android.graphics.Bitmap;
import android.graphics.Typeface_Delegate;
+import android.os.Looper;
import android.util.Finalizers;
import java.lang.ref.SoftReference;
@@ -291,20 +292,20 @@ public final class Bridge extends LayoutBridge {
@Override
public BridgeLayoutScene createScene(SceneParams params) {
try {
- SceneResult lastResult = SceneResult.SUCCESS;
+ SceneResult lastResult = SceneStatus.SUCCESS.getResult();
LayoutSceneImpl scene = new LayoutSceneImpl(params);
try {
- scene.prepareThread();
+ prepareThread();
lastResult = scene.init(params.getTimeout());
- if (lastResult == SceneResult.SUCCESS) {
+ if (lastResult.isSuccess()) {
lastResult = scene.inflate();
- if (lastResult == SceneResult.SUCCESS) {
+ if (lastResult.isSuccess()) {
lastResult = scene.render();
}
}
} finally {
scene.release();
- scene.cleanupThread();
+ cleanupThread();
}
return new BridgeLayoutScene(scene, lastResult);
@@ -339,6 +340,31 @@ public final class Bridge extends LayoutBridge {
}
/**
+ * Prepares the current thread for rendering.
+ *
+ * Note that while this can be called several time, the first call to {@link #cleanupThread()}
+ * will do the clean-up, and make the thread unable to do further scene actions.
+ */
+ public static void prepareThread() {
+ // we need to make sure the Looper has been initialized for this thread.
+ // this is required for View that creates Handler objects.
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ }
+
+ /**
+ * Cleans up thread-specific data. After this, the thread cannot be used for scene actions.
+ * <p>
+ * Note that it doesn't matter how many times {@link #prepareThread()} was called, a single
+ * call to this will prevent the thread from doing further scene actions
+ */
+ public static void cleanupThread() {
+ // clean up the looper
+ Looper.sThreadLocal.remove();
+ }
+
+ /**
* Returns details of a framework resource from its integer value.
* @param value the integer value
* @return an array of 2 strings containing the resource name and type, or null if the id
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
index f807214..2f7ef48 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
@@ -64,14 +64,14 @@ public class BridgeLayoutScene extends LayoutScene {
@Override
public SceneResult render(long timeout) {
try {
- mScene.prepareThread();
+ Bridge.prepareThread();
mLastResult = mScene.acquire(timeout);
- if (mLastResult == SceneResult.SUCCESS) {
+ if (mLastResult.isSuccess()) {
mLastResult = mScene.render();
}
} finally {
mScene.release();
- mScene.cleanupThread();
+ Bridge.cleanupThread();
}
return mLastResult;
@@ -81,40 +81,36 @@ public class BridgeLayoutScene extends LayoutScene {
public SceneResult animate(Object targetObject, String animationName,
boolean isFrameworkAnimation, IAnimationListener listener) {
try {
- mScene.prepareThread();
+ Bridge.prepareThread();
mLastResult = mScene.acquire(SceneParams.DEFAULT_TIMEOUT);
- if (mLastResult == SceneResult.SUCCESS) {
+ if (mLastResult.isSuccess()) {
mLastResult = mScene.animate(targetObject, animationName, isFrameworkAnimation,
listener);
}
} finally {
mScene.release();
- mScene.cleanupThread();
+ Bridge.cleanupThread();
}
return mLastResult;
}
@Override
- public SceneResult insertChild(Object parentView, IXmlPullParser childXml, Object beforeSibling,
+ public SceneResult insertChild(Object parentView, IXmlPullParser childXml, int index,
IAnimationListener listener) {
if (parentView instanceof ViewGroup == false) {
throw new IllegalArgumentException("parentView is not a ViewGroup");
}
- if (beforeSibling != null && beforeSibling instanceof View == false) {
- throw new IllegalArgumentException("beforeSibling is not a View");
- }
try {
- mScene.prepareThread();
+ Bridge.prepareThread();
mLastResult = mScene.acquire(SceneParams.DEFAULT_TIMEOUT);
- if (mLastResult == SceneResult.SUCCESS) {
- mLastResult = mScene.insertChild((ViewGroup) parentView, childXml,
- (View) beforeSibling, listener);
+ if (mLastResult.isSuccess()) {
+ mLastResult = mScene.insertChild((ViewGroup) parentView, childXml, index, listener);
}
} finally {
mScene.release();
- mScene.cleanupThread();
+ Bridge.cleanupThread();
}
return mLastResult;
@@ -122,7 +118,7 @@ public class BridgeLayoutScene extends LayoutScene {
@Override
- public SceneResult moveChild(Object parentView, Object childView, Object beforeSibling,
+ public SceneResult moveChild(Object parentView, Object childView, int index,
IAnimationListener listener) {
if (parentView instanceof ViewGroup == false) {
throw new IllegalArgumentException("parentView is not a ViewGroup");
@@ -130,20 +126,17 @@ public class BridgeLayoutScene extends LayoutScene {
if (childView instanceof View == false) {
throw new IllegalArgumentException("childView is not a View");
}
- if (beforeSibling != null && beforeSibling instanceof View == false) {
- throw new IllegalArgumentException("beforeSibling is not a View");
- }
try {
- mScene.prepareThread();
+ Bridge.prepareThread();
mLastResult = mScene.acquire(SceneParams.DEFAULT_TIMEOUT);
- if (mLastResult == SceneResult.SUCCESS) {
- mLastResult = mScene.moveChild((ViewGroup) parentView, (View) childView,
- (View) beforeSibling, listener);
+ if (mLastResult.isSuccess()) {
+ mLastResult = mScene.moveChild((ViewGroup) parentView, (View) childView, index,
+ listener);
}
} finally {
mScene.release();
- mScene.cleanupThread();
+ Bridge.cleanupThread();
}
return mLastResult;
@@ -156,14 +149,14 @@ public class BridgeLayoutScene extends LayoutScene {
}
try {
- mScene.prepareThread();
+ Bridge.prepareThread();
mLastResult = mScene.acquire(SceneParams.DEFAULT_TIMEOUT);
- if (mLastResult == SceneResult.SUCCESS) {
+ if (mLastResult.isSuccess()) {
mLastResult = mScene.removeChild((View) childView, listener);
}
} finally {
mScene.release();
- mScene.cleanupThread();
+ Bridge.cleanupThread();
}
return mLastResult;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
index d5766ab..2b9d52f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java
@@ -16,8 +16,11 @@
package com.android.layoutlib.bridge.impl;
+import com.android.layoutlib.api.LayoutScene;
import com.android.layoutlib.api.SceneResult;
import com.android.layoutlib.api.LayoutScene.IAnimationListener;
+import com.android.layoutlib.api.SceneResult.SceneStatus;
+import com.android.layoutlib.bridge.Bridge;
import android.animation.Animator;
import android.animation.ValueAnimator;
@@ -57,7 +60,7 @@ public class AnimationThread extends Thread {
@Override
public void run() {
- mScene.prepareThread();
+ Bridge.prepareThread();
try {
Handler_Delegate.setCallback(new IHandlerCallback() {
public void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) {
@@ -75,6 +78,7 @@ public class AnimationThread extends Thread {
mAnimator.start();
// loop the animation
+ LayoutScene scene = mScene.getScene();
do {
// get the next message.
MessageBundle bundle = mQueue.poll();
@@ -88,14 +92,14 @@ public class AnimationThread extends Thread {
try {
sleep(bundle.mUptimeMillis - currentTime);
} catch (InterruptedException e) {
- // TODO Auto-generated catch block
+ // FIXME log/do something/sleep again?
e.printStackTrace();
}
}
// ready to do the work, acquire the scene.
SceneResult result = mScene.acquire(250);
- if (result != SceneResult.SUCCESS) {
+ if (result.isSuccess() == false) {
mListener.done(result);
return;
}
@@ -104,18 +108,18 @@ public class AnimationThread extends Thread {
// the next message, so mQueue will have another one.
try {
bundle.mTarget.handleMessage(bundle.mMessage);
- if (mScene.render() == SceneResult.SUCCESS) {
- mListener.onNewFrame(mScene.getScene());
+ if (mScene.render().isSuccess()) {
+ mListener.onNewFrame(scene);
}
} finally {
mScene.release();
}
} while (mQueue.size() > 0);
- mListener.done(SceneResult.SUCCESS);
+ mListener.done(SceneStatus.SUCCESS.getResult());
} finally {
Handler_Delegate.setCallback(null);
- mScene.cleanupThread();
+ Bridge.cleanupThread();
}
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
index 05d207c..74e7fb2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -51,7 +51,6 @@ import android.graphics.Canvas;
import android.graphics.Canvas_Delegate;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
@@ -104,6 +103,9 @@ public class LayoutSceneImpl {
private int mScreenOffset;
private IResourceValue mWindowBackground;
private FrameLayout mViewRoot;
+ private Canvas mCanvas;
+ private int mMeasuredScreenWidth = -1;
+ private int mMeasuredScreenHeight = -1;
// information being returned through the API
private BufferedImage mImage;
@@ -198,32 +200,7 @@ public class LayoutSceneImpl {
mBlockParser = new BridgeXmlBlockParser(mParams.getLayoutDescription(),
mContext, false /* platformResourceFlag */);
- return SceneResult.SUCCESS;
- }
-
- /**
- * Prepares the current thread for rendering.
- *
- * Note that while this can be called several time, the first call to {@link #cleanupThread()}
- * will do the clean-up, and make the thread unable to do further scene actions.
- */
- public void prepareThread() {
- // we need to make sure the Looper has been initialized for this thread.
- // this is required for View that creates Handler objects.
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
- }
-
- /**
- * Cleans up thread-specific data. After this, the thread cannot be used for scene actions.
- * <p>
- * Note that it doesn't matter how many times {@link #prepareThread()} was called, a single
- * call to this will prevent the thread from doing further scene actions
- */
- public void cleanupThread() {
- // clean up the looper
- Looper.sThreadLocal.remove();
+ return SceneStatus.SUCCESS.getResult();
}
/**
@@ -365,7 +342,7 @@ public class LayoutSceneImpl {
mViewRoot.setBackgroundDrawable(d);
}
- return SceneResult.SUCCESS;
+ return SceneStatus.SUCCESS.getResult();
} catch (PostInflateException e) {
return new SceneResult(SceneStatus.ERROR_INFLATION, e.getMessage(), e);
} catch (Throwable e) {
@@ -389,99 +366,110 @@ public class LayoutSceneImpl {
*
* @throws IllegalStateException if the current context is different than the one owned by
* the scene, or if {@link #acquire(long)} was not called.
+ *
+ * @see SceneParams#getRenderingMode()
*/
public SceneResult render() {
checkLock();
try {
- long current = System.currentTimeMillis();
if (mViewRoot == null) {
return new SceneResult(SceneStatus.ERROR_NOT_INFLATED);
}
// measure the views
int w_spec, h_spec;
- int renderScreenWidth = mParams.getScreenWidth();
- int renderScreenHeight = mParams.getScreenHeight();
-
RenderingMode renderingMode = mParams.getRenderingMode();
- if (renderingMode != RenderingMode.NORMAL) {
- // measure the full size needed by the layout.
- w_spec = MeasureSpec.makeMeasureSpec(renderScreenWidth,
- renderingMode.isHorizExpand() ?
- MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
- : MeasureSpec.EXACTLY);
- h_spec = MeasureSpec.makeMeasureSpec(renderScreenHeight - mScreenOffset,
- renderingMode.isVertExpand() ?
- MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
- : MeasureSpec.EXACTLY);
- mViewRoot.measure(w_spec, h_spec);
-
- if (renderingMode.isHorizExpand()) {
- int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
- if (neededWidth > renderScreenWidth) {
- renderScreenWidth = neededWidth;
+ // only do the screen measure when needed.
+ boolean newRenderSize = false;
+ if (mMeasuredScreenWidth == -1) {
+ newRenderSize = true;
+ mMeasuredScreenWidth = mParams.getScreenWidth();
+ mMeasuredScreenHeight = mParams.getScreenHeight();
+
+ if (renderingMode != RenderingMode.NORMAL) {
+ // measure the full size needed by the layout.
+ w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth,
+ renderingMode.isHorizExpand() ?
+ MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+ : MeasureSpec.EXACTLY);
+ h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight - mScreenOffset,
+ renderingMode.isVertExpand() ?
+ MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+ : MeasureSpec.EXACTLY);
+ mViewRoot.measure(w_spec, h_spec);
+
+ if (renderingMode.isHorizExpand()) {
+ int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
+ if (neededWidth > mMeasuredScreenWidth) {
+ mMeasuredScreenWidth = neededWidth;
+ }
}
- }
- if (renderingMode.isVertExpand()) {
- int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
- if (neededHeight > renderScreenHeight - mScreenOffset) {
- renderScreenHeight = neededHeight + mScreenOffset;
+ if (renderingMode.isVertExpand()) {
+ int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
+ if (neededHeight > mMeasuredScreenHeight - mScreenOffset) {
+ mMeasuredScreenHeight = neededHeight + mScreenOffset;
+ }
}
}
}
// remeasure with the size we need
// This must always be done before the call to layout
- w_spec = MeasureSpec.makeMeasureSpec(renderScreenWidth, MeasureSpec.EXACTLY);
- h_spec = MeasureSpec.makeMeasureSpec(renderScreenHeight - mScreenOffset,
+ w_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenWidth, MeasureSpec.EXACTLY);
+ h_spec = MeasureSpec.makeMeasureSpec(mMeasuredScreenHeight - mScreenOffset,
MeasureSpec.EXACTLY);
mViewRoot.measure(w_spec, h_spec);
// now do the layout.
- mViewRoot.layout(0, mScreenOffset, renderScreenWidth, renderScreenHeight);
+ mViewRoot.layout(0, mScreenOffset, mMeasuredScreenWidth, mMeasuredScreenHeight);
// draw the views
// create the BufferedImage into which the layout will be rendered.
- if (mParams.getImageFactory() != null) {
- mImage = mParams.getImageFactory().getImage(renderScreenWidth,
- renderScreenHeight - mScreenOffset);
- } else {
- mImage = new BufferedImage(renderScreenWidth, renderScreenHeight - mScreenOffset,
- BufferedImage.TYPE_INT_ARGB);
- }
+ if (newRenderSize || mCanvas == null) {
+ if (mParams.getImageFactory() != null) {
+ mImage = mParams.getImageFactory().getImage(mMeasuredScreenWidth,
+ mMeasuredScreenHeight - mScreenOffset);
+ } else {
+ mImage = new BufferedImage(mMeasuredScreenWidth,
+ mMeasuredScreenHeight - mScreenOffset, BufferedImage.TYPE_INT_ARGB);
+ }
- if (mParams.isCustomBackgroundEnabled()) {
- Graphics2D gc = mImage.createGraphics();
- gc.setColor(new Color(mParams.getCustomBackgroundColor(), true));
- gc.fillRect(0, 0, renderScreenWidth, renderScreenHeight - mScreenOffset);
- gc.dispose();
- }
+ if (mParams.isCustomBackgroundEnabled()) {
+ Graphics2D gc = mImage.createGraphics();
+ gc.setColor(new Color(mParams.getCustomBackgroundColor(), true));
+ gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight - mScreenOffset);
+ gc.dispose();
+ }
- // create an Android bitmap around the BufferedImage
- Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
- true /*isMutable*/,
- Density.getEnum(mParams.getDensity()));
+ // create an Android bitmap around the BufferedImage
+ Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
+ true /*isMutable*/,
+ Density.getEnum(mParams.getDensity()));
- // create a Canvas around the Android bitmap
- Canvas canvas = new Canvas(bitmap);
- canvas.setDensity(mParams.getDensity());
+ // create a Canvas around the Android bitmap
+ mCanvas = new Canvas(bitmap);
+ mCanvas.setDensity(mParams.getDensity());
+ }
// to set the logger, get the native delegate
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
+ Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(mCanvas);
canvasDelegate.setLogger(mParams.getLogger());
- mViewRoot.draw(canvas);
- canvasDelegate.dispose();
+ long preDrawTime = System.currentTimeMillis();
+
+ mViewRoot.draw(mCanvas);
+
+ long drawTime = System.currentTimeMillis();
mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
- System.out.println("rendering (ms): " + (System.currentTimeMillis() - current));
+ System.out.println(String.format("rendering (ms): %03d", drawTime - preDrawTime));
// success!
- return SceneResult.SUCCESS;
+ return SceneStatus.SUCCESS.getResult();
} catch (Throwable e) {
// get the real cause of the exception.
Throwable t = e;
@@ -532,7 +520,7 @@ public class LayoutSceneImpl {
new AnimationThread(this, anim, listener).start();
- return SceneResult.SUCCESS;
+ return SceneStatus.SUCCESS.getResult();
}
} catch (Exception e) {
// get the real cause of the exception.
@@ -549,14 +537,9 @@ public class LayoutSceneImpl {
}
public SceneResult insertChild(ViewGroup parentView, IXmlPullParser childXml,
- View beforeSibling, IAnimationListener listener) {
+ int index, IAnimationListener listener) {
checkLock();
- int index = parentView.indexOfChild(beforeSibling);
- if (beforeSibling != null && index == -1) {
- throw new IllegalArgumentException("beforeSibling not in parentView");
- }
-
// create a block parser for the XML
BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(childXml, mContext,
false /* platformResourceFlag */);
@@ -567,28 +550,42 @@ public class LayoutSceneImpl {
View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
// add it to the parentView in the correct location
- parentView.addView(child, index);
+ try {
+ parentView.addView(child, index);
+ } catch (UnsupportedOperationException e) {
+ // looks like this is a view class that doesn't support children manipulation!
+ return new SceneResult(SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN);
+ }
- return render();
+ invalidateRenderingSize();
+
+ SceneResult result = render();
+ if (result.isSuccess()) {
+ result.setData(child);
+ }
+
+ return result;
}
- public SceneResult moveChild(ViewGroup parentView, View childView, View beforeSibling,
+ public SceneResult moveChild(ViewGroup parentView, View childView, int index,
IAnimationListener listener) {
checkLock();
- int index = parentView.indexOfChild(beforeSibling);
- if (beforeSibling != null && index == -1) {
- throw new IllegalArgumentException("beforeSibling not in parentView");
- }
+ try {
+ ViewParent parent = childView.getParent();
+ if (parent instanceof ViewGroup) {
+ ViewGroup parentGroup = (ViewGroup) parent;
+ parentGroup.removeView(childView);
+ }
- ViewParent parent = childView.getParent();
- if (parent instanceof ViewGroup) {
- ViewGroup parentGroup = (ViewGroup) parent;
- parentGroup.removeView(childView);
+ // add it to the parentView in the correct location
+ parentView.addView(childView, index);
+ } catch (UnsupportedOperationException e) {
+ // looks like this is a view class that doesn't support children manipulation!
+ return new SceneResult(SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN);
}
- // add it to the parentView in the correct location
- parentView.addView(childView, index);
+ invalidateRenderingSize();
return render();
}
@@ -596,12 +593,19 @@ public class LayoutSceneImpl {
public SceneResult removeChild(View childView, IAnimationListener listener) {
checkLock();
- ViewParent parent = childView.getParent();
- if (parent instanceof ViewGroup) {
- ViewGroup parentGroup = (ViewGroup) parent;
- parentGroup.removeView(childView);
+ try {
+ ViewParent parent = childView.getParent();
+ if (parent instanceof ViewGroup) {
+ ViewGroup parentGroup = (ViewGroup) parent;
+ parentGroup.removeView(childView);
+ }
+ } catch (UnsupportedOperationException e) {
+ // looks like this is a view class that doesn't support children manipulation!
+ return new SceneResult(SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN);
}
+ invalidateRenderingSize();
+
return render();
}
@@ -971,6 +975,10 @@ public class LayoutSceneImpl {
return result;
}
+ private void invalidateRenderingSize() {
+ mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
+ }
+
public BufferedImage getImage() {
return mImage;
}
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index 6ec223b..097b109 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -16,6 +16,7 @@
#include <ui/KeyCharacterMap.h>
#include <ui/KeyLayoutMap.h>
+#include <ui/VirtualKeyMap.h>
#include <utils/String8.h>
#include <stdio.h>
@@ -30,6 +31,7 @@ enum FileType {
FILETYPE_UNKNOWN,
FILETYPE_KEYLAYOUT,
FILETYPE_KEYCHARACTERMAP,
+ FILETYPE_VIRTUALKEYDEFINITION,
};
@@ -37,8 +39,10 @@ static void usage() {
fprintf(stderr, "Keymap Validation Tool\n\n");
fprintf(stderr, "Usage:\n");
fprintf(stderr,
- " %s [FILENAME.kl] [FILENAME.kcm] [...]\n"
- " Validates the specified key layout and/or key character map files.\n\n", gProgName);
+ " %s [*.kl] [*.kcm] [virtualkeys.*] [...]\n"
+ " Validates the specified key layouts, key character maps \n"
+ " or virtual key definitions.\n\n",
+ gProgName);
}
static FileType getFileType(const char* filename) {
@@ -51,6 +55,11 @@ static FileType getFileType(const char* filename) {
return FILETYPE_KEYCHARACTERMAP;
}
}
+
+ if (strstr(filename, "virtualkeys.")) {
+ return FILETYPE_VIRTUALKEYDEFINITION;
+ }
+
return FILETYPE_UNKNOWN;
}
@@ -60,7 +69,7 @@ static bool validateFile(const char* filename) {
FileType fileType = getFileType(filename);
switch (fileType) {
case FILETYPE_UNKNOWN:
- fprintf(stderr, "File extension must be .kl or .kcm.\n\n");
+ fprintf(stderr, "Supported file types: *.kl, *.kcm, virtualkeys.*\n\n");
return false;
case FILETYPE_KEYLAYOUT: {
@@ -82,6 +91,16 @@ static bool validateFile(const char* filename) {
}
break;
}
+
+ case FILETYPE_VIRTUALKEYDEFINITION: {
+ VirtualKeyMap* map;
+ status_t status = VirtualKeyMap::load(String8(filename), &map);
+ if (status) {
+ fprintf(stderr, "Error %d parsing virtual key definition file.\n\n", status);
+ return false;
+ }
+ break;
+ }
}
fputs("No errors.\n\n", stdout);