Merge "Dismiss the ticker early if the status bar is tapped." into honeycomb
diff --git a/Android.mk b/Android.mk
index 7728b02..93e1c4f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -367,6 +367,7 @@
-since ./frameworks/base/api/7.xml 7 \
-since ./frameworks/base/api/8.xml 8 \
-since ./frameworks/base/api/9.xml 9 \
+ -since ./frameworks/base/api/10.xml 10 \
-since ./frameworks/base/api/current.xml Honeycomb \
-werror -hide 113 \
-overview $(LOCAL_PATH)/core/java/overview.html
diff --git a/NOTICE b/NOTICE
index d857ba3..462d5ae 100644
--- a/NOTICE
+++ b/NOTICE
@@ -56,6 +56,16 @@
=========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
+ == in this case for Additional Codecs code. ==
+ =========================================================================
+
+Additional Codecs
+These files are Copyright 2003-2010 VisualOn, but released under
+the Apache2 License.
+
+ =========================================================================
+ == NOTICE file corresponding to the section 4 d of ==
+ == the Apache License, Version 2.0, ==
== in this case for the TagSoup code. ==
=========================================================================
diff --git a/api/current.xml b/api/current.xml
index bd59694..5d42845 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -118502,6 +118502,66 @@
deprecated="not deprecated"
visibility="public"
>
+<method name="disableForegroundDispatch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activity" type="android.app.Activity">
+</parameter>
+</method>
+<method name="disableForegroundNdefPush"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activity" type="android.app.Activity">
+</parameter>
+</method>
+<method name="enableForegroundDispatch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activity" type="android.app.Activity">
+</parameter>
+<parameter name="intent" type="android.app.PendingIntent">
+</parameter>
+<parameter name="filters" type="android.content.IntentFilter[]">
+</parameter>
+<parameter name="techLists" type="java.lang.String[][]">
+</parameter>
+</method>
+<method name="enableForegroundNdefPush"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activity" type="android.app.Activity">
+</parameter>
+<parameter name="msg" type="android.nfc.NdefMessage">
+</parameter>
+</method>
<method name="getDefaultAdapter"
return="android.nfc.NfcAdapter"
abstract="false"
@@ -118537,6 +118597,17 @@
visibility="public"
>
</method>
+<field name="ACTION_NDEF_DISCOVERED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.nfc.action.NDEF_DISCOVERED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ACTION_TAG_DISCOVERED"
type="java.lang.String"
transient="false"
@@ -118548,6 +118619,17 @@
visibility="public"
>
</field>
+<field name="ACTION_TECHNOLOGY_DISCOVERED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.nfc.action.TECH_DISCOVERED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EXTRA_ID"
type="java.lang.String"
transient="false"
@@ -118570,6 +118652,17 @@
visibility="public"
>
</field>
+<field name="EXTRA_TAG"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.nfc.extra.TAG""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="NfcManager"
extends="java.lang.Object"
@@ -118591,6 +118684,1295 @@
>
</method>
</class>
+<class name="Tag"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="createMockTag"
+ return="android.nfc.Tag"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="byte[]">
+</parameter>
+<parameter name="techList" type="int[]">
+</parameter>
+<parameter name="techListExtras" type="android.os.Bundle[]">
+</parameter>
+</method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getId"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTechList"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="TagLostException"
+ extends="java.io.IOException"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="TagLostException"
+ type="android.nfc.TagLostException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="TagLostException"
+ type="android.nfc.TagLostException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="message" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
+</package>
+<package name="android.nfc.tech"
+>
+<class name="BasicTagTechnology"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility=""
+>
+<implements name="android.nfc.tech.TagTechnology">
+</implements>
+<method name="close"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="connect"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getTag"
+ return="android.nfc.Tag"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isConnected"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reconnect"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="IsoDep"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="android.nfc.tech.IsoDep"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="getHiLayerResponse"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getHistoricalBytes"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setTimeout"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeout" type="int">
+</parameter>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="MifareClassic"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="authenticateSectorWithKeyA"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sectorIndex" type="int">
+</parameter>
+<parameter name="key" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="authenticateSectorWithKeyB"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sectorIndex" type="int">
+</parameter>
+<parameter name="key" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="blockToSector"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="blockIndex" type="int">
+</parameter>
+</method>
+<method name="decrement"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="blockIndex" type="int">
+</parameter>
+<parameter name="value" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="get"
+ return="android.nfc.tech.MifareClassic"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="getBlockCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBlockCountInSector"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sectorIndex" type="int">
+</parameter>
+</method>
+<method name="getSectorCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSize"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="increment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="blockIndex" type="int">
+</parameter>
+<parameter name="value" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="readBlock"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="blockIndex" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="restore"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="blockIndex" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="sectorToBlock"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sectorIndex" type="int">
+</parameter>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="transfer"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="blockIndex" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeBlock"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="blockIndex" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="BLOCK_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEY_DEFAULT"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEY_MIFARE_APPLICATION_DIRECTORY"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEY_NFC_FORUM"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_1K"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1024"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_2K"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2048"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_4K"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SIZE_MINI"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="320"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_CLASSIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_PLUS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_PRO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="MifareUltralight"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="android.nfc.tech.MifareUltralight"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="readPages"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pageOffset" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writePage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pageOffset" type="int">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="PAGE_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_ULTRALIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_ULTRALIGHT_C"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TYPE_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Ndef"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="canMakeReadonly"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="get"
+ return="android.nfc.tech.Ndef"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="getCachedNdefMessage"
+ return="android.nfc.NdefMessage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMaxSize"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNdefMessage"
+ return="android.nfc.NdefMessage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isWritable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="makeReadonly"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="writeNdefMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msg" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<field name="MIFARE_CLASSIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="101"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_FORUM_TYPE_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_FORUM_TYPE_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_FORUM_TYPE_3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NFC_FORUM_TYPE_4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OTHER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="NdefFormatable"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="format"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="firstMessage" type="android.nfc.NdefMessage">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="get"
+ return="android.nfc.tech.NdefFormatable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+</class>
+<class name="NfcA"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="android.nfc.tech.NfcA"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="getAtqa"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSak"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="NfcB"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="android.nfc.tech.NfcB"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="getApplicationData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProtocolInfo"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="NfcF"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="android.nfc.tech.NfcF"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="getManufacturer"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSystemCode"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="NfcV"
+ extends="android.nfc.tech.BasicTagTechnology"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="android.nfc.tech.NfcV"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
+<method name="getDsfId"
+ return="byte"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getResponseFlags"
+ return="byte"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="transceive"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<interface name="TagTechnology"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.io.Closeable">
+</implements>
+<method name="close"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="connect"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getTag"
+ return="android.nfc.Tag"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reconnect"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</interface>
</package>
<package name="android.opengl"
>
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 3c45080..8b6b819 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -655,7 +655,7 @@
boolean mCalled;
boolean mCheckedForLoaderManager;
boolean mLoadersStarted;
- private boolean mResumed;
+ /*package*/ boolean mResumed;
private boolean mStopped;
boolean mFinished;
boolean mStartedActivity;
@@ -4363,9 +4363,8 @@
mLastNonConfigurationInstances = null;
- // First call onResume() -before- setting mResumed, so we don't
- // send out any status bar / menu notifications the client makes.
mCalled = false;
+ // mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);
if (!mCalled) {
throw new SuperNotCalledException(
@@ -4374,7 +4373,6 @@
}
// Now really resume, and install the current status bar and menu.
- mResumed = true;
mCalled = false;
mFragments.dispatchResume();
@@ -4399,6 +4397,7 @@
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
+ mResumed = false;
}
final void performUserLeaving() {
@@ -4461,7 +4460,10 @@
}
}
- final boolean isResumed() {
+ /**
+ * @hide
+ */
+ public final boolean isResumed() {
return mResumed;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 960b943..8f9a76b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -193,6 +193,9 @@
final HashMap<IBinder, ProviderClientRecord> mLocalProviders
= new HashMap<IBinder, ProviderClientRecord>();
+ final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
+ = new HashMap<Activity, ArrayList<OnActivityPausedListener>>();
+
final GcIdler mGcIdler = new GcIdler();
boolean mGcIdlerScheduled = false;
@@ -1514,6 +1517,28 @@
}
}
+ public void registerOnActivityPausedListener(Activity activity,
+ OnActivityPausedListener listener) {
+ synchronized (mOnPauseListeners) {
+ ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
+ if (list == null) {
+ list = new ArrayList<OnActivityPausedListener>();
+ mOnPauseListeners.put(activity, list);
+ }
+ list.add(listener);
+ }
+ }
+
+ public void unregisterOnActivityPausedListener(Activity activity,
+ OnActivityPausedListener listener) {
+ synchronized (mOnPauseListeners) {
+ ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
+ if (list != null) {
+ list.remove(listener);
+ }
+ }
+ }
+
public final ActivityInfo resolveActivityInfo(Intent intent) {
ActivityInfo aInfo = intent.resolveActivityInfo(
mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
@@ -2454,6 +2479,17 @@
}
}
r.paused = true;
+
+ // Notify any outstanding on paused listeners
+ ArrayList<OnActivityPausedListener> listeners;
+ synchronized (mOnPauseListeners) {
+ listeners = mOnPauseListeners.remove(r.activity);
+ }
+ int size = (listeners != null ? listeners.size() : 0);
+ for (int i = 0; i < size; i++) {
+ listeners.get(i).onPaused(r.activity);
+ }
+
return state;
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index ad811d8..cd278be 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1149,6 +1149,7 @@
* @param activity The activity being resumed.
*/
public void callActivityOnResume(Activity activity) {
+ activity.mResumed = true;
activity.onResume();
if (mActivityMonitors != null) {
diff --git a/core/java/android/app/OnActivityPausedListener.java b/core/java/android/app/OnActivityPausedListener.java
new file mode 100644
index 0000000..379f133
--- /dev/null
+++ b/core/java/android/app/OnActivityPausedListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app;
+
+/**
+ * A listener that is called when an Activity is paused. Since this is tracked client side
+ * it should not be trusted to represent the exact current state, but can be used as a hint
+ * for cleanup.
+ *
+ * @hide
+ */
+public interface OnActivityPausedListener {
+ /**
+ * Called when the given activity is paused.
+ */
+ public void onPaused(Activity activity);
+}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 4a75514..f079e42 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -25,6 +25,7 @@
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
import android.view.IRotationWatcher;
import android.view.IWindowManager;
import android.view.Surface;
@@ -489,6 +490,8 @@
private final Handler mHandler;
private SensorEvent mValuesPool;
public SparseBooleanArray mSensors = new SparseBooleanArray();
+ public SparseBooleanArray mFirstEvent = new SparseBooleanArray();
+ public SparseIntArray mSensorAccuracies = new SparseIntArray();
ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
mSensorEventListener = listener;
@@ -499,10 +502,30 @@
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
- SensorEvent t = (SensorEvent)msg.obj;
- if (t.accuracy >= 0) {
- mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
+ final SensorEvent t = (SensorEvent)msg.obj;
+ final int handle = t.sensor.getHandle();
+
+ switch (t.sensor.getType()) {
+ // Only report accuracy for sensors that support it.
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ case Sensor.TYPE_ORIENTATION:
+ // call onAccuracyChanged() only if the value changes
+ final int accuracy = mSensorAccuracies.get(handle);
+ if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
+ mSensorAccuracies.put(handle, t.accuracy);
+ mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
+ }
+ break;
+ default:
+ // For other sensors, just report the accuracy once
+ if (mFirstEvent.get(handle) == false) {
+ mFirstEvent.put(handle, true);
+ mSensorEventListener.onAccuracyChanged(
+ t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
+ }
+ break;
}
+
mSensorEventListener.onSensorChanged(t);
returnToPool(t);
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index a99256f..feb246e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1065,7 +1065,7 @@
public boolean onEvaluateInputViewShown() {
Configuration config = getResources().getConfiguration();
return config.keyboard == Configuration.KEYBOARD_NOKEYS
- || config.hardKeyboardHidden == Configuration.KEYBOARDHIDDEN_YES;
+ || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES;
}
/**
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 7e809f5..cab8ed2 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -221,6 +221,8 @@
/** {@hide} */
public static final int TYPE_DUMMY = 8;
+ /** {@hide} */
+ public static final int TYPE_ETHERNET = 9;
/** {@hide} TODO: Need to adjust this for WiMAX. */
public static final int MAX_RADIO_TYPE = TYPE_DUMMY;
/** {@hide} TODO: Need to adjust this for WiMAX. */
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index a663fb8..d439a48 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -16,8 +16,12 @@
package android.nfc;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.Tag;
+import android.nfc.TechListParcel;
import android.nfc.ILlcpSocket;
import android.nfc.ILlcpServiceSocket;
import android.nfc.ILlcpConnectionlessSocket;
@@ -44,6 +48,11 @@
NdefMessage localGet();
void localSet(in NdefMessage message);
void openTagConnection(in Tag tag);
+ void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent,
+ in IntentFilter[] filters, in TechListParcel techLists);
+ void disableForegroundDispatch(in ComponentName activity);
+ void enableForegroundNdefPush(in ComponentName activity, in NdefMessage msg);
+ void disableForegroundNdefPush(in ComponentName activity);
// Non-public methods
// TODO: check and complete
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index 5d222d9..57dc38c 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -17,6 +17,7 @@
package android.nfc;
import android.nfc.NdefMessage;
+import android.nfc.TransceiveResult;
/**
* @hide
@@ -30,7 +31,7 @@
byte[] getUid(int nativeHandle);
boolean isNdef(int nativeHandle);
boolean isPresent(int nativeHandle);
- byte[] transceive(int nativeHandle, in byte[] data, boolean raw);
+ TransceiveResult transceive(int nativeHandle, in byte[] data, boolean raw);
int getLastError(int nativeHandle);
@@ -39,4 +40,7 @@
int ndefMakeReadOnly(int nativeHandle);
boolean ndefIsWritable(int nativeHandle);
int formatNdef(int nativeHandle, in byte[] key);
+
+ void setIsoDepTimeout(int timeout);
+ void resetIsoDepTimeout();
}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 758c8a0..4808032 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -18,11 +18,16 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Activity;
import android.app.ActivityThread;
+import android.app.OnActivityPausedListener;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.IBinder;
+import android.os.Parcel;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
@@ -43,7 +48,6 @@
*
* If any activities respond to this intent neither
* {@link #ACTION_TECHNOLOGY_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started.
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
@@ -51,13 +55,12 @@
/**
* Intent to started when a tag is discovered. The data URI is formated as
* {@code vnd.android.nfc://tag/} with the path having a directory entry for each technology
- * in the {@link Tag#getTechnologyList()} is ascending order.
+ * in the {@link Tag#getTechList()} is sorted ascending order.
*
* This intent is started after {@link #ACTION_NDEF_DISCOVERED} and before
* {@link #ACTION_TAG_DISCOVERED}
*
* If any activities respond to this intent {@link #ACTION_TAG_DISCOVERED} will not be started.
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_TECHNOLOGY_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
@@ -76,7 +79,6 @@
/**
* Mandatory Tag extra for the ACTION_TAG intents.
- * @hide
*/
public static final String EXTRA_TAG = "android.nfc.extra.TAG";
@@ -102,6 +104,20 @@
"android.nfc.action.TRANSACTION_DETECTED";
/**
+ * Broadcast Action: an RF field ON has been detected.
+ * @hide
+ */
+ public static final String ACTION_RF_FIELD_ON_DETECTED =
+ "android.nfc.action.RF_FIELD_ON_DETECTED";
+
+ /**
+ * Broadcast Action: an RF Field OFF has been detected.
+ * @hide
+ */
+ public static final String ACTION_RF_FIELD_OFF_DETECTED =
+ "android.nfc.action.RF_FIELD_OFF_DETECTED";
+
+ /**
* Broadcast Action: an adapter's state changed between enabled and disabled.
*
* The new value is stored in the extra EXTRA_NEW_BOOLEAN_STATE and just contains
@@ -197,8 +213,7 @@
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
// recovery
private static INfcAdapter sService;
-
- private final Context mContext;
+ private static INfcTag sTagService;
/**
* Helper to check if this device has FEATURE_NFC, but without using
@@ -235,6 +250,12 @@
Log.e(TAG, "could not retrieve NFC service");
return null;
}
+ try {
+ sTagService = sService.getNfcTagInterface();
+ } catch (RemoteException e) {
+ Log.e(TAG, "could not retrieve NFC Tag service");
+ return null;
+ }
}
return sService;
}
@@ -289,7 +310,6 @@
if (setupService() == null) {
throw new UnsupportedOperationException();
}
- mContext = context;
}
/**
@@ -297,10 +317,20 @@
* @hide
*/
public INfcAdapter getService() {
+ isEnabled(); // NOP call to recover sService if it is stale
return sService;
}
/**
+ * Returns the binder interface to the tag service.
+ * @hide
+ */
+ public INfcTag getTagService() {
+ isEnabled(); // NOP call to recover sTagService if it is stale
+ return sTagService;
+ }
+
+ /**
* NFC service dead - attempt best effort recovery
* @hide
*/
@@ -309,11 +339,21 @@
INfcAdapter service = getServiceInterface();
if (service == null) {
Log.e(TAG, "could not retrieve NFC service during service recovery");
+ // nothing more can be done now, sService is still stale, we'll hit
+ // this recovery path again later
return;
}
- /* assigning to sService is not thread-safe, but this is best-effort code
- * and on a well-behaved system should never happen */
+ // assigning to sService is not thread-safe, but this is best-effort code
+ // and on a well-behaved system should never happen
sService = service;
+ try {
+ sTagService = service.getNfcTagInterface();
+ } catch (RemoteException ee) {
+ Log.e(TAG, "could not retrieve NFC tag service during service recovery");
+ // nothing more can be done now, sService is still stale, we'll hit
+ // this recovery path again later
+ }
+
return;
}
@@ -374,6 +414,136 @@
}
/**
+ * Enables foreground dispatching to the given Activity. This will force all NFC Intents that
+ * match the given filters to be delivered to the activity bypassing the standard dispatch
+ * mechanism. If no IntentFilters are given all the PendingIntent will be invoked for every
+ * dispatch Intent.
+ *
+ * This method must be called from the main thread.
+ *
+ * @param activity the Activity to dispatch to
+ * @param intent the PendingIntent to start for the dispatch
+ * @param filters the IntentFilters to override dispatching for, or null to always dispatch
+ * @throws IllegalStateException
+ */
+ public void enableForegroundDispatch(Activity activity, PendingIntent intent,
+ IntentFilter[] filters, String[][] techLists) {
+ if (activity == null || intent == null) {
+ throw new NullPointerException();
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalStateException("Foregorund dispatching can only be enabled " +
+ "when your activity is resumed");
+ }
+ try {
+ TechListParcel parcel = null;
+ if (techLists != null && techLists.length > 0) {
+ parcel = new TechListParcel(techLists);
+ }
+ ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
+ mForegroundDispatchListener);
+ sService.enableForegroundDispatch(activity.getComponentName(), intent, filters,
+ parcel);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ }
+ }
+
+ /**
+ * Disables foreground activity dispatching setup with
+ * {@link #enableForegroundDispatch}.
+ *
+ * <p>This must be called before the Activity returns from
+ * it's <code>onPause()</code> or this method will throw an IllegalStateException.
+ *
+ * <p>This method must be called from the main thread.
+ */
+ public void disableForegroundDispatch(Activity activity) {
+ ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
+ mForegroundDispatchListener);
+ disableForegroundDispatchInternal(activity, false);
+ }
+
+ OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() {
+ @Override
+ public void onPaused(Activity activity) {
+ disableForegroundDispatchInternal(activity, true);
+ }
+ };
+
+ void disableForegroundDispatchInternal(Activity activity, boolean force) {
+ try {
+ sService.disableForegroundDispatch(activity.getComponentName());
+ if (!force && !activity.isResumed()) {
+ throw new IllegalStateException("You must disable forgeground dispatching " +
+ "while your activity is still resumed");
+ }
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ }
+ }
+
+ /**
+ * Enable NDEF message push over P2P while this Activity is in the foreground. For this to
+ * function properly the other NFC device being scanned must support the "com.android.npp"
+ * NDEF push protocol.
+ *
+ * <p><em>NOTE</em> While foreground NDEF push is active standard tag dispatch is disabled.
+ * Only the foreground activity may receive tag discovered dispatches via
+ * {@link #enableForegroundDispatch}.
+ */
+ public void enableForegroundNdefPush(Activity activity, NdefMessage msg) {
+ if (activity == null || msg == null) {
+ throw new NullPointerException();
+ }
+ if (!activity.isResumed()) {
+ throw new IllegalStateException("Foregorund NDEF push can only be enabled " +
+ "when your activity is resumed");
+ }
+ try {
+ ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
+ mForegroundNdefPushListener);
+ sService.enableForegroundNdefPush(activity.getComponentName(), msg);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ }
+ }
+
+ /**
+ * Disables foreground NDEF push setup with
+ * {@link #enableForegroundNdefPush}.
+ *
+ * <p>This must be called before the Activity returns from
+ * it's <code>onPause()</code> or this method will throw an IllegalStateException.
+ *
+ * <p>This method must be called from the main thread.
+ */
+ public void disableForegroundNdefPush(Activity activity) {
+ ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
+ mForegroundNdefPushListener);
+ disableForegroundNdefPushInternal(activity, false);
+ }
+
+ OnActivityPausedListener mForegroundNdefPushListener = new OnActivityPausedListener() {
+ @Override
+ public void onPaused(Activity activity) {
+ disableForegroundNdefPushInternal(activity, true);
+ }
+ };
+
+ void disableForegroundNdefPushInternal(Activity activity, boolean force) {
+ try {
+ sService.disableForegroundNdefPush(activity.getComponentName());
+ if (!force && !activity.isResumed()) {
+ throw new IllegalStateException("You must disable forgeground NDEF push " +
+ "while your activity is still resumed");
+ }
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ }
+ }
+
+ /**
* Set the NDEF Message that this NFC adapter should appear as to Tag
* readers.
* <p>
diff --git a/core/java/android/nfc/NfcSecureElement.java b/core/java/android/nfc/NfcSecureElement.java
index 5f4c066..ea2846e 100755
--- a/core/java/android/nfc/NfcSecureElement.java
+++ b/core/java/android/nfc/NfcSecureElement.java
@@ -16,7 +16,7 @@
package android.nfc;
-import android.nfc.technology.TagTechnology;
+import android.nfc.tech.TagTechnology;
import android.os.RemoteException;
import android.util.Log;
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 7404950..aae75c9 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,36 +16,35 @@
package android.nfc;
-import android.nfc.technology.IsoDep;
-import android.nfc.technology.MifareClassic;
-import android.nfc.technology.MifareUltralight;
-import android.nfc.technology.NfcV;
-import android.nfc.technology.Ndef;
-import android.nfc.technology.NdefFormatable;
-import android.nfc.technology.NfcA;
-import android.nfc.technology.NfcB;
-import android.nfc.technology.NfcF;
-import android.nfc.technology.TagTechnology;
+import android.nfc.tech.IsoDep;
+import android.nfc.tech.MifareClassic;
+import android.nfc.tech.MifareUltralight;
+import android.nfc.tech.Ndef;
+import android.nfc.tech.NdefFormatable;
+import android.nfc.tech.NfcA;
+import android.nfc.tech.NfcB;
+import android.nfc.tech.NfcF;
+import android.nfc.tech.NfcV;
+import android.nfc.tech.TagTechnology;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.RemoteException;
import java.util.Arrays;
/**
* Represents a (generic) discovered tag.
* <p>
- * A tag is a passive NFC element, such as NFC Forum Tag's, Mifare class Tags,
- * Sony Felica Tags.
+ * A tag is a passive NFC element, such as NFC Forum Tag's, MIFARE class Tags,
+ * Sony FeliCa Tags, etc.
* <p>
* Tag's have a type and usually have a UID.
* <p>
* {@link Tag} objects are passed to applications via the {@link NfcAdapter#EXTRA_TAG} extra
* in {@link NfcAdapter#ACTION_TAG_DISCOVERED} intents. A {@link Tag} object is immutable
* and represents the state of the tag at the time of discovery. It can be
- * directly queried for its UID and Type, or used to create a {@link TagTechnology}
- * (with {@link Tag#getTechnology(int)}).
+ * directly queried for its UID and Type, or used to create a {@link TagTechnology} using the
+ * static <code>get()</code> methods on the varios tech classes.
* <p>
* A {@link Tag} can be used to create a {@link TagTechnology} only while the tag is in
* range. If it is removed and then returned to range, then the most recent
@@ -55,13 +54,14 @@
* time and calls on this class will retrieve those read-only properties, and
* not cause any further RF activity or block. Note however that arrays passed to and
* returned by this class are *not* cloned, so be careful not to modify them.
- * @hide
*/
public class Tag implements Parcelable {
/*package*/ final byte[] mId;
/*package*/ final int[] mTechList;
+ /*package*/ final String[] mTechStringList;
/*package*/ final Bundle[] mTechExtras;
/*package*/ final int mServiceHandle; // for use by NFC service, 0 indicates a mock
+ /*package*/ final INfcTag mTagService;
/*package*/ int mConnectedTechnology;
@@ -69,24 +69,26 @@
* Hidden constructor to be used by NFC service and internal classes.
* @hide
*/
- public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle) {
+ public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle,
+ INfcTag tagService) {
if (techList == null) {
throw new IllegalArgumentException("rawTargets cannot be null");
}
mId = id;
mTechList = Arrays.copyOf(techList, techList.length);
+ mTechStringList = generateTechStringList(techList);
// Ensure mTechExtras is as long as mTechList
mTechExtras = Arrays.copyOf(techListExtras, techList.length);
mServiceHandle = serviceHandle;
+ mTagService = tagService;
mConnectedTechnology = -1;
}
/**
* Construct a mock Tag.
- * <p>This is an application constructed tag, so NfcAdapter methods on this
- * Tag such as {@link #getTechnology} may fail with
- * {@link IllegalArgumentException} since it does not represent a physical Tag.
+ * <p>This is an application constructed tag, so NfcAdapter methods on this Tag may fail
+ * with {@link IllegalArgumentException} since it does not represent a physical Tag.
* <p>This constructor might be useful for mock testing.
* @param id The tag identifier, can be null
* @param techList must not be null
@@ -94,7 +96,46 @@
*/
public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) {
// set serviceHandle to 0 to indicate mock tag
- return new Tag(id, techList, techListExtras, 0);
+ return new Tag(id, techList, techListExtras, 0, null);
+ }
+
+ private String[] generateTechStringList(int[] techList) {
+ final int size = techList.length;
+ String[] strings = new String[size];
+ for (int i = 0; i < size; i++) {
+ switch (techList[i]) {
+ case TagTechnology.ISO_DEP:
+ strings[i] = IsoDep.class.getName();
+ break;
+ case TagTechnology.MIFARE_CLASSIC:
+ strings[i] = MifareClassic.class.getName();
+ break;
+ case TagTechnology.MIFARE_ULTRALIGHT:
+ strings[i] = MifareUltralight.class.getName();
+ break;
+ case TagTechnology.NDEF:
+ strings[i] = Ndef.class.getName();
+ break;
+ case TagTechnology.NDEF_FORMATABLE:
+ strings[i] = NdefFormatable.class.getName();
+ break;
+ case TagTechnology.NFC_A:
+ strings[i] = NfcA.class.getName();
+ break;
+ case TagTechnology.NFC_B:
+ strings[i] = NfcB.class.getName();
+ break;
+ case TagTechnology.NFC_F:
+ strings[i] = NfcF.class.getName();
+ break;
+ case TagTechnology.NFC_V:
+ strings[i] = NfcV.class.getName();
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown tech type " + techList[i]);
+ }
+ }
+ return strings;
}
/**
@@ -119,19 +160,24 @@
* Returns technologies present in the tag that this implementation understands,
* or a zero length array if there are no supported technologies on this tag.
*
- * The elements of the list are guaranteed be one of the constants defined in
- * {@link TagTechnology}.
+ * The elements of the list are the names of the classes implementing the technology.
*
* The ordering of the returned array is undefined and should not be relied upon.
*/
- public int[] getTechnologyList() {
- return Arrays.copyOf(mTechList, mTechList.length);
+ public String[] getTechList() {
+ return mTechStringList;
}
- /**
- * Returns the technology, or null if not present
- */
- public TagTechnology getTechnology(NfcAdapter adapter, int tech) {
+ /** @hide */
+ public boolean hasTech(int techType) {
+ for (int tech : mTechList) {
+ if (tech == techType) return true;
+ }
+ return false;
+ }
+
+ /** @hide */
+ public Bundle getTechExtras(int tech) {
int pos = -1;
for (int idx = 0; idx < mTechList.length; idx++) {
if (mTechList[idx] == tech) {
@@ -143,44 +189,12 @@
return null;
}
- Bundle extras = mTechExtras[pos];
- try {
- switch (tech) {
- case TagTechnology.NFC_A: {
- return new NfcA(adapter, this, extras);
- }
- case TagTechnology.NFC_B: {
- return new NfcB(adapter, this, extras);
- }
- case TagTechnology.ISO_DEP: {
- return new IsoDep(adapter, this, extras);
- }
- case TagTechnology.NFC_V: {
- return new NfcV(adapter, this, extras);
- }
- case TagTechnology.NDEF: {
- return new Ndef(adapter, this, tech, extras);
- }
- case TagTechnology.NDEF_FORMATABLE: {
- return new NdefFormatable(adapter, this, tech, extras);
- }
- case TagTechnology.NFC_F: {
- return new NfcF(adapter, this, extras);
- }
- case TagTechnology.MIFARE_CLASSIC: {
- return new MifareClassic(adapter, this, extras);
- }
- case TagTechnology.MIFARE_ULTRALIGHT: {
- return new MifareUltralight(adapter, this, extras);
- }
+ return mTechExtras[pos];
+ }
- default: {
- throw new UnsupportedOperationException("Tech " + tech + " not supported");
- }
- }
- } catch (RemoteException e) {
- return null;
- }
+ /** @hide */
+ public INfcTag getTagService() {
+ return mTagService;
}
@Override
@@ -222,25 +236,41 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ // Null mTagService means this is a mock tag
+ int isMock = (mTagService == null)?1:0;
+
writeBytesWithNull(dest, mId);
dest.writeInt(mTechList.length);
dest.writeIntArray(mTechList);
dest.writeTypedArray(mTechExtras, 0);
dest.writeInt(mServiceHandle);
+ dest.writeInt(isMock);
+ if (isMock == 0) {
+ dest.writeStrongBinder(mTagService.asBinder());
+ }
}
public static final Parcelable.Creator<Tag> CREATOR =
new Parcelable.Creator<Tag>() {
@Override
public Tag createFromParcel(Parcel in) {
+ INfcTag tagService;
+
// Tag fields
byte[] id = Tag.readBytesWithNull(in);
int[] techList = new int[in.readInt()];
in.readIntArray(techList);
Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR);
int serviceHandle = in.readInt();
+ int isMock = in.readInt();
+ if (isMock == 0) {
+ tagService = INfcTag.Stub.asInterface(in.readStrongBinder());
+ }
+ else {
+ tagService = null;
+ }
- return new Tag(id, techList, techExtras, serviceHandle);
+ return new Tag(id, techList, techExtras, serviceHandle, tagService);
}
@Override
@@ -249,7 +279,9 @@
}
};
- /*
+ /**
+ * For internal use only.
+ *
* @hide
*/
public synchronized void setConnectedTechnology(int technology) {
@@ -260,14 +292,18 @@
}
}
- /*
+ /**
+ * For internal use only.
+ *
* @hide
*/
public int getConnectedTechnology() {
return mConnectedTechnology;
}
- /*
+ /**
+ * For internal use only.
+ *
* @hide
*/
public void setTechnologyDisconnected() {
diff --git a/core/java/android/nfc/TagLostException.java b/core/java/android/nfc/TagLostException.java
new file mode 100644
index 0000000..1981d7c
--- /dev/null
+++ b/core/java/android/nfc/TagLostException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+import java.io.IOException;
+
+public class TagLostException extends IOException {
+ public TagLostException() {
+ super();
+ }
+
+ public TagLostException(String message) {
+ super(message);
+ }
+}
diff --git a/core/java/android/nfc/TechListParcel.aidl b/core/java/android/nfc/TechListParcel.aidl
new file mode 100644
index 0000000..92e646f
--- /dev/null
+++ b/core/java/android/nfc/TechListParcel.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+parcelable TechListParcel;
\ No newline at end of file
diff --git a/core/java/android/nfc/TechListParcel.java b/core/java/android/nfc/TechListParcel.java
new file mode 100644
index 0000000..396f0f1
--- /dev/null
+++ b/core/java/android/nfc/TechListParcel.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.nfc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class TechListParcel implements Parcelable {
+
+ private String[][] mTechLists;
+
+ public TechListParcel(String[]... strings) {
+ mTechLists = strings;
+ }
+
+ public String[][] getTechLists() {
+ return mTechLists;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ int count = mTechLists.length;
+ dest.writeInt(count);
+ for (int i = 0; i < count; i++) {
+ String[] techList = mTechLists[i];
+ dest.writeStringArray(techList);
+ }
+ }
+
+ public static final Creator<TechListParcel> CREATOR = new Creator<TechListParcel>() {
+ @Override
+ public TechListParcel createFromParcel(Parcel source) {
+ int count = source.readInt();
+ String[][] techLists = new String[count][];
+ for (int i = 0; i < count; i++) {
+ techLists[i] = source.readStringArray();
+ }
+ return new TechListParcel(techLists);
+ }
+
+ @Override
+ public TechListParcel[] newArray(int size) {
+ return new TechListParcel[size];
+ }
+ };
+}
diff --git a/core/java/android/nfc/TransceiveResult.aidl b/core/java/android/nfc/TransceiveResult.aidl
new file mode 100644
index 0000000..98f92ee
--- /dev/null
+++ b/core/java/android/nfc/TransceiveResult.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+parcelable TransceiveResult;
diff --git a/core/java/android/nfc/TransceiveResult.java b/core/java/android/nfc/TransceiveResult.java
new file mode 100644
index 0000000..16244b8
--- /dev/null
+++ b/core/java/android/nfc/TransceiveResult.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Class used to pipe transceive result from the NFC service.
+ *
+ * @hide
+ */
+public final class TransceiveResult implements Parcelable {
+ private final boolean mTagLost;
+ private final boolean mSuccess;
+ private final byte[] mResponseData;
+
+ public TransceiveResult(final boolean success, final boolean tagIsLost,
+ final byte[] data) {
+ mSuccess = success;
+ mTagLost = tagIsLost;
+ mResponseData = data;
+ }
+
+ public boolean isSuccessful() {
+ return mSuccess;
+ }
+
+ public boolean isTagLost() {
+ return mTagLost;
+ }
+
+ public byte[] getResponseData() {
+ return mResponseData;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSuccess ? 1 : 0);
+ dest.writeInt(mTagLost ? 1 : 0);
+ if (mSuccess) {
+ dest.writeInt(mResponseData.length);
+ dest.writeByteArray(mResponseData);
+ }
+ }
+
+ public static final Parcelable.Creator<TransceiveResult> CREATOR =
+ new Parcelable.Creator<TransceiveResult>() {
+ @Override
+ public TransceiveResult createFromParcel(Parcel in) {
+ boolean success = (in.readInt() == 1) ? true : false;
+ boolean tagLost = (in.readInt() == 1) ? true : false;
+ byte[] responseData;
+
+ if (success) {
+ int responseLength = in.readInt();
+ responseData = new byte[responseLength];
+ in.readByteArray(responseData);
+ } else {
+ responseData = null;
+ }
+ return new TransceiveResult(success, tagLost, responseData);
+ }
+
+ @Override
+ public TransceiveResult[] newArray(int size) {
+ return new TransceiveResult[size];
+ }
+ };
+
+}
diff --git a/core/java/android/nfc/tech/BasicTagTechnology.java b/core/java/android/nfc/tech/BasicTagTechnology.java
new file mode 100644
index 0000000..32a850d
--- /dev/null
+++ b/core/java/android/nfc/tech/BasicTagTechnology.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.ErrorCodes;
+import android.nfc.Tag;
+import android.nfc.TagLostException;
+import android.nfc.TransceiveResult;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * A base class for tag technologies that are built on top of transceive().
+ */
+/* package */ abstract class BasicTagTechnology implements TagTechnology {
+ private static final String TAG = "NFC";
+
+ /*package*/ final Tag mTag;
+ /*package*/ boolean mIsConnected;
+ /*package*/ int mSelectedTechnology;
+
+ BasicTagTechnology(Tag tag, int tech) throws RemoteException {
+ mTag = tag;
+ mSelectedTechnology = tech;
+ }
+
+ @Override
+ public Tag getTag() {
+ return mTag;
+ }
+
+ /** Internal helper to throw IllegalStateException if the technology isn't connected */
+ void checkConnected() {
+ if ((mTag.getConnectedTechnology() != mSelectedTechnology) ||
+ (mTag.getConnectedTechnology() == -1)) {
+ throw new IllegalStateException("Call connect() first!");
+ }
+ }
+
+ /**
+ * Helper to indicate if {@link #connect} has succeeded.
+ * <p>
+ * Does not cause RF activity, and does not block.
+ * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed
+ * to be within range. Applications must still handle {@link java.io.IOException}
+ * while using methods that require a connection in case the connection is lost after this
+ * method returns.
+ */
+ public boolean isConnected() {
+ if (!mIsConnected) {
+ return false;
+ }
+
+ try {
+ return mTag.getTagService().isPresent(mTag.getServiceHandle());
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ return false;
+ }
+ }
+
+ @Override
+ public void connect() throws IOException {
+ try {
+ int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(),
+ mSelectedTechnology);
+
+ if (errorCode == ErrorCodes.SUCCESS) {
+ // Store this in the tag object
+ mTag.setConnectedTechnology(mSelectedTechnology);
+ mIsConnected = true;
+ } else {
+ throw new IOException();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ throw new IOException("NFC service died");
+ }
+ }
+
+ @Override
+ public void reconnect() throws IOException {
+ if (!mIsConnected) {
+ throw new IllegalStateException("Technology not connected yet");
+ }
+
+ try {
+ int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle());
+
+ if (errorCode != ErrorCodes.SUCCESS) {
+ mIsConnected = false;
+ mTag.setTechnologyDisconnected();
+ throw new IOException();
+ }
+ } catch (RemoteException e) {
+ mIsConnected = false;
+ mTag.setTechnologyDisconnected();
+ Log.e(TAG, "NFC service dead", e);
+ throw new IOException("NFC service died");
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ /* Note that we don't want to physically disconnect the tag,
+ * but just reconnect to it to reset its state
+ */
+ mTag.getTagService().reconnect(mTag.getServiceHandle());
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ } finally {
+ mIsConnected = false;
+ mTag.setTechnologyDisconnected();
+ }
+ }
+
+ /** Internal transceive */
+ /*package*/ byte[] transceive(byte[] data, boolean raw) throws IOException {
+ checkConnected();
+
+ try {
+ TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(),
+ data, raw);
+ if (result == null) {
+ throw new IOException("transceive failed");
+ } else {
+ if (result.isSuccessful()) {
+ return result.getResponseData();
+ } else {
+ if (result.isTagLost()) {
+ throw new TagLostException("Tag was lost.");
+ }
+ else {
+ throw new IOException("transceive failed");
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ throw new IOException("NFC service died");
+ }
+ }
+}
diff --git a/core/java/android/nfc/tech/IsoDep.java b/core/java/android/nfc/tech/IsoDep.java
new file mode 100644
index 0000000..774982e
--- /dev/null
+++ b/core/java/android/nfc/tech/IsoDep.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+
+/**
+ * A low-level connection to a {@link Tag} using the ISO-DEP technology, also known as
+ * ISO1443-4.
+ *
+ * <p>You can acquire this kind of connection with {@link #get}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * <p>Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class IsoDep extends BasicTagTechnology {
+ private static final String TAG = "NFC";
+
+ /** @hide */
+ public static final String EXTRA_HI_LAYER_RESP = "hiresp";
+ /** @hide */
+ public static final String EXTRA_HIST_BYTES = "histbytes";
+
+ private byte[] mHiLayerResponse = null;
+ private byte[] mHistBytes = null;
+
+ /**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static IsoDep get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.ISO_DEP)) return null;
+ try {
+ return new IsoDep(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public IsoDep(Tag tag)
+ throws RemoteException {
+ super(tag, TagTechnology.ISO_DEP);
+ Bundle extras = tag.getTechExtras(TagTechnology.ISO_DEP);
+ if (extras != null) {
+ mHiLayerResponse = extras.getByteArray(EXTRA_HI_LAYER_RESP);
+ mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES);
+ }
+ }
+
+ /**
+ * Sets the timeout of an IsoDep transceive transaction in milliseconds.
+ * If the transaction has not completed before the timeout,
+ * any ongoing {@link #transceive} operation will be
+ * aborted and the connection to the tag is lost. This setting is applied
+ * only to the {@link Tag} object linked to this technology and will be
+ * reset when {@link IsoDep#close} is called.
+ * The default transaction timeout is 300 milliseconds.
+ */
+ public void setTimeout(int timeout) {
+ try {
+ mTag.getTagService().setIsoDepTimeout(timeout);
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ try {
+ mTag.getTagService().resetIsoDepTimeout();
+ } catch (RemoteException e) {
+ Log.e(TAG, "NFC service dead", e);
+ }
+ super.close();
+ }
+
+ /**
+ * Return the historical bytes if the tag is using {@link NfcA}, null otherwise.
+ */
+ public byte[] getHistoricalBytes() {
+ return mHistBytes;
+ }
+
+ /**
+ * Return the hi layer response bytes if the tag is using {@link NfcB}, null otherwise.
+ */
+ public byte[] getHiLayerResponse() {
+ return mHiLayerResponse;
+ }
+
+ /**
+ * Send data to a tag and receive the response.
+ * <p>
+ * This method will block until the response is received. It can be canceled
+ * with {@link #close}.
+ * <p>Requires {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param data bytes to send
+ * @return bytes received in response
+ * @throws IOException if the target is lost or connection closed
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
+}
diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java
new file mode 100644
index 0000000..d337ead
--- /dev/null
+++ b/core/java/android/nfc/tech/MifareClassic.java
@@ -0,0 +1,432 @@
+/*
+ * 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.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.Tag;
+import android.nfc.TagLostException;
+import android.os.RemoteException;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Technology class representing MIFARE Classic tags (also known as MIFARE Standard).
+ *
+ * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology
+ * MIFARE Classic tags will still be scanned, but will only show the NfcA technology.
+ *
+ * <p>MIFARE Classic tags have sectors that each contain blocks. The block size is constant at
+ * 16 bytes, but the number of sectors and the sector size varies by product. MIFARE has encryption
+ * built in and each sector has two keys associated with it, as well as ACLs to determine what
+ * level acess each key grants. Before operating on a sector you must call either
+ * {@link #authenticateSectorWithKeyA(int, byte[])} or
+ * {@link #authenticateSectorWithKeyB(int, byte[])} to gain authorization for your request.
+ */
+public final class MifareClassic extends BasicTagTechnology {
+ /**
+ * The well-known default MIFARE read key. All keys are set to this at the factory.
+ * Using this key will effectively make the payload in the sector public.
+ */
+ public static final byte[] KEY_DEFAULT =
+ {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
+ /**
+ * The well-known, default MIFARE Application Directory read key.
+ */
+ public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY =
+ {(byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5};
+ /**
+ * The well-known, default read key for NDEF data on a MIFARE Classic
+ */
+ public static final byte[] KEY_NFC_FORUM =
+ {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
+
+ /** A Mifare Classic compatible card of unknown type */
+ public static final int TYPE_UNKNOWN = -1;
+ /** A MIFARE Classic tag */
+ public static final int TYPE_CLASSIC = 0;
+ /** A MIFARE Plus tag */
+ public static final int TYPE_PLUS = 1;
+ /** A MIFARE Pro tag */
+ public static final int TYPE_PRO = 2;
+
+ /** The tag contains 16 sectors, each holding 4 blocks. */
+ public static final int SIZE_1K = 1024;
+ /** The tag contains 32 sectors, each holding 4 blocks. */
+ public static final int SIZE_2K = 2048;
+ /**
+ * The tag contains 40 sectors. The first 32 sectors contain 4 blocks and the last 8 sectors
+ * contain 16 blocks.
+ */
+ public static final int SIZE_4K = 4096;
+ /** The tag contains 5 sectors, each holding 4 blocks. */
+ public static final int SIZE_MINI = 320;
+
+ /** Size of a Mifare Classic block (in bytes) */
+ public static final int BLOCK_SIZE = 16;
+
+ private static final int MAX_BLOCK_COUNT = 256;
+ private static final int MAX_SECTOR_COUNT = 40;
+
+ private boolean mIsEmulated;
+ private int mType;
+ private int mSize;
+
+ /**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static MifareClassic get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.MIFARE_CLASSIC)) return null;
+ try {
+ return new MifareClassic(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public MifareClassic(Tag tag) throws RemoteException {
+ super(tag, TagTechnology.MIFARE_CLASSIC);
+
+ NfcA a = NfcA.get(tag); // Mifare Classic is always based on NFC a
+
+ mIsEmulated = false;
+
+ switch (a.getSak()) {
+ case 0x08:
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_1K;
+ break;
+ case 0x09:
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_MINI;
+ break;
+ case 0x10:
+ mType = TYPE_PLUS;
+ mSize = SIZE_2K;
+ // SecLevel = SL2
+ break;
+ case 0x11:
+ mType = TYPE_PLUS;
+ mSize = SIZE_4K;
+ // Seclevel = SL2
+ break;
+ case 0x18:
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_4K;
+ break;
+ case 0x28:
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_1K;
+ mIsEmulated = true;
+ break;
+ case 0x38:
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_4K;
+ mIsEmulated = true;
+ break;
+ case 0x88:
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_1K;
+ // NXP-tag: false
+ break;
+ case 0x98:
+ case 0xB8:
+ mType = TYPE_PRO;
+ mSize = SIZE_4K;
+ break;
+ default:
+ // Stack incorrectly reported a MifareClassic. We cannot handle this
+ // gracefully - we have no idea of the memory layout. Bail.
+ throw new RuntimeException(
+ "Tag incorrectly enumerated as Mifare Classic, SAK = " + a.getSak());
+ }
+ }
+
+ /** Returns the type of the tag, determined at discovery time */
+ public int getType() {
+ return mType;
+ }
+
+ /** Returns the size of the tag in bytes, determined at discovery time */
+ public int getSize() {
+ return mSize;
+ }
+
+ /** Returns true if the tag is emulated, determined at discovery time.
+ * These are actually smart-cards that emulate a Mifare Classic interface.
+ * They can be treated identically to a Mifare Classic tag.
+ * @hide
+ */
+ public boolean isEmulated() {
+ return mIsEmulated;
+ }
+
+ /** Returns the number of sectors on this tag, determined at discovery time */
+ public int getSectorCount() {
+ switch (mSize) {
+ case SIZE_1K:
+ return 16;
+ case SIZE_2K:
+ return 32;
+ case SIZE_4K:
+ return 40;
+ case SIZE_MINI:
+ return 5;
+ default:
+ return 0;
+ }
+ }
+
+ /** Returns the total block count, determined at discovery time */
+ public int getBlockCount() {
+ return mSize / BLOCK_SIZE;
+ }
+
+ /** Returns the block count for the given sector, determined at discovery time */
+ public int getBlockCountInSector(int sectorIndex) {
+ validateSector(sectorIndex);
+
+ if (sectorIndex < 32) {
+ return 4;
+ } else {
+ return 16;
+ }
+ }
+
+ /** Return the sector index of a given block */
+ public int blockToSector(int blockIndex) {
+ validateBlock(blockIndex);
+
+ if (blockIndex < 32 * 4) {
+ return blockIndex / 4;
+ } else {
+ return 32 + (blockIndex - 32 * 4) / 16;
+ }
+ }
+
+ /** Return the first block of a given sector */
+ public int sectorToBlock(int sectorIndex) {
+ if (sectorIndex < 32) {
+ return sectorIndex * 4;
+ } else {
+ return 32 * 4 + (sectorIndex - 32) * 16;
+ }
+ }
+
+ // Methods that require connect()
+ /**
+ * Authenticate a sector.
+ * <p>Every sector has an A and B key with different access privileges,
+ * this method attempts to authenticate against the A key.
+ * <p>This requires a that the tag be connected.
+ */
+ public boolean authenticateSectorWithKeyA(int sectorIndex, byte[] key) throws IOException {
+ return authenticate(sectorIndex, key, true);
+ }
+
+ /**
+ * Authenticate a sector.
+ * <p>Every sector has an A and B key with different access privileges,
+ * this method attempts to authenticate against the B key.
+ * <p>This requires a that the tag be connected.
+ */
+ public boolean authenticateSectorWithKeyB(int sectorIndex, byte[] key) throws IOException {
+ return authenticate(sectorIndex, key, false);
+ }
+
+ private boolean authenticate(int sector, byte[] key, boolean keyA) throws IOException {
+ validateSector(sector);
+ checkConnected();
+
+ byte[] cmd = new byte[12];
+
+ // First byte is the command
+ if (keyA) {
+ cmd[0] = 0x60; // phHal_eMifareAuthentA
+ } else {
+ cmd[0] = 0x61; // phHal_eMifareAuthentB
+ }
+
+ // Second byte is block address
+ // Authenticate command takes a block address. Authenticating a block
+ // of a sector will authenticate the entire sector.
+ cmd[1] = (byte) sectorToBlock(sector);
+
+ // Next 4 bytes are last 4 bytes of UID
+ byte[] uid = getTag().getId();
+ System.arraycopy(uid, uid.length - 4, cmd, 2, 4);
+
+ // Next 6 bytes are key
+ System.arraycopy(key, 0, cmd, 6, 6);
+
+ try {
+ if (transceive(cmd, false) != null) {
+ return true;
+ }
+ } catch (TagLostException e) {
+ throw e;
+ } catch (IOException e) {
+ // No need to deal with, will return false anyway
+ }
+ return false;
+ }
+
+ /**
+ * Read 16-byte block.
+ * <p>This requires a that the tag be connected.
+ * @throws IOException
+ */
+ public byte[] readBlock(int blockIndex) throws IOException {
+ validateBlock(blockIndex);
+ checkConnected();
+
+ byte[] cmd = { 0x30, (byte) blockIndex };
+ return transceive(cmd, false);
+ }
+
+ /**
+ * Write 16-byte block.
+ * <p>This requires a that the tag be connected.
+ * @throws IOException
+ */
+ public void writeBlock(int blockIndex, byte[] data) throws IOException {
+ validateBlock(blockIndex);
+ checkConnected();
+ if (data.length != 16) {
+ throw new IllegalArgumentException("must write 16-bytes");
+ }
+
+ byte[] cmd = new byte[data.length + 2];
+ cmd[0] = (byte) 0xA0; // MF write command
+ cmd[1] = (byte) blockIndex;
+ System.arraycopy(data, 0, cmd, 2, data.length);
+
+ transceive(cmd, false);
+ }
+
+ /**
+ * Increment a value block, and store the result in temporary memory.
+ * @param blockIndex
+ * @throws IOException
+ */
+ public void increment(int blockIndex, int value) throws IOException {
+ validateBlock(blockIndex);
+ validateValueOperand(value);
+ checkConnected();
+
+ ByteBuffer cmd = ByteBuffer.allocate(6);
+ cmd.order(ByteOrder.LITTLE_ENDIAN);
+ cmd.put( (byte) 0xC1 );
+ cmd.put( (byte) blockIndex );
+ cmd.putInt(value);
+
+ transceive(cmd.array(), false);
+ }
+
+ /**
+ * Decrement a value block, and store the result in temporary memory.
+ * @param blockIndex
+ * @throws IOException
+ */
+ public void decrement(int blockIndex, int value) throws IOException {
+ validateBlock(blockIndex);
+ validateValueOperand(value);
+ checkConnected();
+
+ ByteBuffer cmd = ByteBuffer.allocate(6);
+ cmd.order(ByteOrder.LITTLE_ENDIAN);
+ cmd.put( (byte) 0xC0 );
+ cmd.put( (byte) blockIndex );
+ cmd.putInt(value);
+
+ transceive(cmd.array(), false);
+ }
+
+ /**
+ * Copy from temporary memory to value block.
+ * @param blockIndex
+ * @throws IOException
+ */
+ public void transfer(int blockIndex) throws IOException {
+ validateBlock(blockIndex);
+ checkConnected();
+
+ byte[] cmd = { (byte) 0xB0, (byte) blockIndex };
+
+ transceive(cmd, false);
+ }
+
+ /**
+ * Copy from value block to temporary memory.
+ * @param blockIndex
+ * @throws IOException
+ */
+ public void restore(int blockIndex) throws IOException {
+ validateBlock(blockIndex);
+ checkConnected();
+
+ byte[] cmd = { (byte) 0xC2, (byte) blockIndex };
+
+ transceive(cmd, false);
+ }
+
+ /**
+ * Send raw NfcA data to a tag and receive the response.
+ * <p>
+ * This method will block until the response is received. It can be canceled
+ * with {@link #close}.
+ * <p>Requires {@link android.Manifest.permission#NFC} permission.
+ * <p>This requires a that the tag be connected.
+ *
+ * @param data bytes to send
+ * @return bytes received in response
+ * @throws IOException if the target is lost or connection closed
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
+
+ private static void validateSector(int sector) {
+ // Do not be too strict on upper bounds checking, since some cards
+ // have more addressable memory than they report. For example,
+ // Mifare Plus 2k cards will appear as Mifare Classic 1k cards when in
+ // Mifare Classic compatibility mode.
+ // Note that issuing a command to an out-of-bounds block is safe - the
+ // tag should report error causing IOException. This validation is a
+ // helper to guard against obvious programming mistakes.
+ if (sector < 0 || sector >= MAX_SECTOR_COUNT) {
+ throw new IndexOutOfBoundsException("sector out of bounds: " + sector);
+ }
+ }
+
+ private static void validateBlock(int block) {
+ // Just looking for obvious out of bounds...
+ if (block < 0 || block >= MAX_BLOCK_COUNT) {
+ throw new IndexOutOfBoundsException("block out of bounds: " + block);
+ }
+ }
+
+ private static void validateValueOperand(int value) {
+ if (value < 0) {
+ throw new IllegalArgumentException("value operand negative");
+ }
+ }
+}
diff --git a/core/java/android/nfc/tech/MifareUltralight.java b/core/java/android/nfc/tech/MifareUltralight.java
new file mode 100644
index 0000000..b514f1c
--- /dev/null
+++ b/core/java/android/nfc/tech/MifareUltralight.java
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.Tag;
+import android.os.RemoteException;
+
+import java.io.IOException;
+
+//TOOD: Ultralight C 3-DES authentication, one-way counter
+
+/**
+ * Technology class representing MIFARE Ultralight and MIFARE Ultralight C tags.
+ *
+ * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology
+ * MIFARE Ultralight class tags will still be scanned, but will only show the NfcA technology.
+ *
+ * <p>MIFARE Ultralight compatible tags have 4 byte pages. The read command
+ * returns 4 pages (16 bytes) at a time, for speed. The write command operates
+ * on a single page (4 bytes) to minimize EEPROM write cycles.
+ *
+ * <p>The original MIFARE Ultralight consists of a 64 byte EEPROM. The first
+ * 4 pages are for the OTP area, manufacturer data, and locking bits. They are
+ * readable and some bits are writable. The final 12 pages are the user
+ * read/write area. For more information see the NXP data sheet MF0ICU1.
+ *
+ * <p>The MIFARE Ultralight C consists of a 192 byte EEPROM. The first 4 pages
+ * are for OTP, manufacturer data, and locking bits. The next 36 pages are the
+ * user read/write area. The next 4 pages are additional locking bits, counters
+ * and authentication configuration and are readable. The final 4 pages are for
+ * the authentication key and are not readable. For more information see the
+ * NXP data sheet MF0ICU2.
+ */
+public final class MifareUltralight extends BasicTagTechnology {
+ /** A MIFARE Ultralight compatible tag of unknown type */
+ public static final int TYPE_UNKNOWN = -1;
+ /** A MIFARE Ultralight tag */
+ public static final int TYPE_ULTRALIGHT = 1;
+ /** A MIFARE Ultralight C tag */
+ public static final int TYPE_ULTRALIGHT_C = 2;
+
+ /** Size of a MIFARE Ultralight page in bytes */
+ public static final int PAGE_SIZE = 4;
+
+ private static final int NXP_MANUFACTURER_ID = 0x04;
+ private static final int MAX_PAGE_COUNT = 256;
+
+ private int mType;
+
+ /**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static MifareUltralight get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.MIFARE_ULTRALIGHT)) return null;
+ try {
+ return new MifareUltralight(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public MifareUltralight(Tag tag) throws RemoteException {
+ super(tag, TagTechnology.MIFARE_ULTRALIGHT);
+
+ // Check if this could actually be a Mifare
+ NfcA a = NfcA.get(tag);
+
+ mType = TYPE_UNKNOWN;
+
+ if (a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID) {
+ // could be UL or UL-C
+ //TODO: stack should use NXP AN1303 procedure to make a best guess
+ // attempt at classifying Ultralight vs Ultralight C.
+ mType = TYPE_ULTRALIGHT;
+ }
+ }
+
+ /** Returns the type of the tag.
+ * <p>It is very hard to always accurately classify a MIFARE Ultralight
+ * compatible tag as Ultralight original or Ultralight C. So consider
+ * {@link #getType} a hint. */
+ public int getType() {
+ return mType;
+ }
+
+ // Methods that require connect()
+ /**
+ * Read 4 pages (16 bytes).
+ * <p>The MIFARE Ultralight protocol always reads 4 pages at a time.
+ * <p>If the read spans past the last readable block, then the tag will
+ * return pages that have been wrapped back to the first blocks. MIFARE
+ * Ultralight tags have readable blocks 0x00 through 0x0F. So a read to
+ * block offset 0x0E would return blocks 0x0E, 0x0F, 0x00, 0x01. MIFARE
+ * Ultralight C tags have readable blocks 0x00 through 0x2B. So a read to
+ * block 0x2A would return blocks 0x2A, 0x2B, 0x00, 0x01.
+ * <p>This requires that the tag be connected.
+ *
+ * @return 4 pages (16 bytes)
+ * @throws IOException
+ */
+ public byte[] readPages(int pageOffset) throws IOException {
+ validatePageOffset(pageOffset);
+ checkConnected();
+
+ byte[] cmd = { 0x30, (byte) pageOffset};
+ return transceive(cmd, false);
+ }
+
+ /**
+ * Write 1 page (4 bytes).
+ * <p>The MIFARE Ultralight protocol always writes 1 page at a time.
+ * <p>This requires that the tag be connected.
+ *
+ * @param pageOffset The offset of the page to write
+ * @param data The data to write
+ * @throws IOException
+ */
+ public void writePage(int pageOffset, byte[] data) throws IOException {
+ validatePageOffset(pageOffset);
+ checkConnected();
+
+ byte[] cmd = new byte[data.length + 2];
+ cmd[0] = (byte) 0xA2;
+ cmd[1] = (byte) pageOffset;
+ System.arraycopy(data, 0, cmd, 2, data.length);
+
+ transceive(cmd, false);
+ }
+
+ /**
+ * Send raw NfcA data to a tag and receive the response.
+ * <p>
+ * This method will block until the response is received. It can be canceled
+ * with {@link #close}.
+ * <p>Requires {@link android.Manifest.permission#NFC} permission.
+ * <p>This requires a that the tag be connected.
+ *
+ * @param data bytes to send
+ * @return bytes received in response
+ * @throws IOException if the target is lost or connection closed
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
+
+ private static void validatePageOffset(int pageOffset) {
+ // Do not be too strict on upper bounds checking, since some cards
+ // may have more addressable memory than they report.
+ // Note that issuing a command to an out-of-bounds block is safe - the
+ // tag will wrap the read to an addressable area. This validation is a
+ // helper to guard against obvious programming mistakes.
+ if (pageOffset < 0 || pageOffset >= MAX_PAGE_COUNT) {
+ throw new IndexOutOfBoundsException("page out of bounds: " + pageOffset);
+ }
+ }
+}
diff --git a/core/java/android/nfc/technology/Ndef.java b/core/java/android/nfc/tech/Ndef.java
similarity index 69%
rename from core/java/android/nfc/technology/Ndef.java
rename to core/java/android/nfc/tech/Ndef.java
index 05872fe..c6804f9 100644
--- a/core/java/android/nfc/technology/Ndef.java
+++ b/core/java/android/nfc/tech/Ndef.java
@@ -14,30 +14,34 @@
* limitations under the License.
*/
-package android.nfc.technology;
+package android.nfc.tech;
import android.nfc.ErrorCodes;
import android.nfc.FormatException;
+import android.nfc.INfcTag;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
+import android.util.Log;
import java.io.IOException;
/**
* A high-level connection to a {@link Tag} using one of the NFC type 1, 2, 3, or 4 technologies
* to interact with NDEF data. MiFare Classic cards that present NDEF data may also be used
- * via this class. To determine the exact technology being used call {@link #getTechnologyId()}
+ * via this class. To determine the exact technology being used call {@link #getType()}
*
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link #get}.
*
* <p class="note"><strong>Note:</strong>
* Use of this class requires the {@link android.Manifest.permission#NFC}
* permission.
*/
public final class Ndef extends BasicTagTechnology {
+ private static final String TAG = "NFC";
+
/** @hide */
public static final int NDEF_MODE_READ_ONLY = 1;
/** @hide */
@@ -57,14 +61,12 @@
/** @hide */
public static final String EXTRA_NDEF_TYPE = "ndeftype";
- //TODO: consider removing OTHER entirely - and not allowing Ndef to
- // enumerate for tag types outside of (NFC Forum 1-4, MifareClassic)
public static final int OTHER = -1;
public static final int NFC_FORUM_TYPE_1 = 1;
public static final int NFC_FORUM_TYPE_2 = 2;
public static final int NFC_FORUM_TYPE_3 = 3;
public static final int NFC_FORUM_TYPE_4 = 4;
- public static final int MIFARE_CLASSIC = 105;
+ public static final int MIFARE_CLASSIC = 101;
private final int mMaxNdefSize;
private final int mCardState;
@@ -72,11 +74,27 @@
private final int mNdefType;
/**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static Ndef get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.NDEF)) return null;
+ try {
+ return new Ndef(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Internal constructor, to be used by NfcAdapter
* @hide
*/
- public Ndef(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
- super(adapter, tag, tech);
+ public Ndef(Tag tag) throws RemoteException {
+ super(tag, TagTechnology.NDEF);
+ Bundle extras = tag.getTechExtras(TagTechnology.NDEF);
if (extras != null) {
mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);
mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE);
@@ -97,15 +115,6 @@
}
/**
- * Get optional extra NDEF messages.
- * Some tags may contain extra NDEF messages, but not all
- * implementations will be able to read them.
- */
- public NdefMessage[] getExtraNdefMessage() throws IOException, FormatException {
- throw new UnsupportedOperationException();
- }
-
- /**
* Get NDEF tag type.
* <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2},
* {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4},
@@ -148,11 +157,12 @@
checkConnected();
try {
+ INfcTag tagService = mTag.getTagService();
int serviceHandle = mTag.getServiceHandle();
- if (mTagService.isNdef(serviceHandle)) {
- NdefMessage msg = mTagService.ndefRead(serviceHandle);
+ if (tagService.isNdef(serviceHandle)) {
+ NdefMessage msg = tagService.ndefRead(serviceHandle);
if (msg == null) {
- int errorCode = mTagService.getLastError(serviceHandle);
+ int errorCode = tagService.getLastError(serviceHandle);
switch (errorCode) {
case ErrorCodes.ERROR_IO:
throw new IOException();
@@ -168,7 +178,7 @@
return null;
}
} catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
+ Log.e(TAG, "NFC service dead", e);
return null;
}
}
@@ -181,9 +191,10 @@
checkConnected();
try {
+ INfcTag tagService = mTag.getTagService();
int serviceHandle = mTag.getServiceHandle();
- if (mTagService.isNdef(serviceHandle)) {
- int errorCode = mTagService.ndefWrite(serviceHandle, msg);
+ if (tagService.isNdef(serviceHandle)) {
+ int errorCode = tagService.ndefWrite(serviceHandle, msg);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
@@ -200,67 +211,54 @@
throw new IOException("Tag is not ndef");
}
} catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
+ Log.e(TAG, "NFC service dead", e);
}
}
/**
- * Attempt to write extra NDEF messages.
- * Implementations may be able to write extra NDEF
- * message after the first primary message, but it is not
- * guaranteed. Even if it can be written, other implementations
- * may not be able to read NDEF messages after the primary message.
- * It is recommended to use additional NDEF records instead.
- *
- * @throws IOException
+ * Indicates whether a tag can be made read-only with
+ * {@link #makeReadonly()}
*/
- public void writeExtraNdefMessage(int i, NdefMessage msg) throws IOException, FormatException {
- checkConnected();
-
- throw new UnsupportedOperationException();
+ public boolean canMakeReadonly() {
+ if (mNdefType == NFC_FORUM_TYPE_1 || mNdefType == NFC_FORUM_TYPE_2) {
+ return true;
+ } else {
+ return false;
+ }
}
/**
- * Set the CC field to indicate this tag is read-only
+ * Sets the CC field to indicate this tag is read-only
+ * and permanently sets the lock bits to prevent any further NDEF
+ * modifications.
+ * This is a one-way process and can not be reverted!
* @throws IOException
*/
public boolean makeReadonly() throws IOException {
checkConnected();
try {
- int errorCode = mTagService.ndefMakeReadOnly(mTag.getServiceHandle());
- switch (errorCode) {
- case ErrorCodes.SUCCESS:
- return true;
- case ErrorCodes.ERROR_IO:
- throw new IOException();
- case ErrorCodes.ERROR_INVALID_PARAM:
- return false;
- default:
- // Should not happen
- throw new IOException();
- }
+ INfcTag tagService = mTag.getTagService();
+ if (tagService.isNdef(mTag.getServiceHandle())) {
+ int errorCode = tagService.ndefMakeReadOnly(mTag.getServiceHandle());
+ switch (errorCode) {
+ case ErrorCodes.SUCCESS:
+ return true;
+ case ErrorCodes.ERROR_IO:
+ throw new IOException();
+ case ErrorCodes.ERROR_INVALID_PARAM:
+ return false;
+ default:
+ // Should not happen
+ throw new IOException();
+ }
+ }
+ else {
+ throw new IOException("Tag is not ndef");
+ }
} catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
+ Log.e(TAG, "NFC service dead", e);
return false;
}
}
-
- /**
- * Attempt to use tag specific technology to really make
- * the tag read-only
- * For NFC Forum Type 1 and 2 only.
- */
- public void makeLowLevelReadonly() {
- checkConnected();
-
- throw new UnsupportedOperationException();
- }
-
- @Override
- public byte[] transceive(byte[] data) {
- checkConnected();
-
- throw new UnsupportedOperationException();
- }
}
diff --git a/core/java/android/nfc/technology/NdefFormatable.java b/core/java/android/nfc/tech/NdefFormatable.java
similarity index 70%
rename from core/java/android/nfc/technology/NdefFormatable.java
rename to core/java/android/nfc/tech/NdefFormatable.java
index 222c558..2919c43 100644
--- a/core/java/android/nfc/technology/NdefFormatable.java
+++ b/core/java/android/nfc/tech/NdefFormatable.java
@@ -14,34 +14,52 @@
* limitations under the License.
*/
-package android.nfc.technology;
+package android.nfc.tech;
import android.nfc.ErrorCodes;
import android.nfc.FormatException;
+import android.nfc.INfcTag;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
-import android.os.Bundle;
import android.os.RemoteException;
+import android.util.Log;
import java.io.IOException;
/**
* An interface to a {@link Tag} allowing to format the tag as NDEF.
*
- * <p>You can acquire this kind of interface with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link #get}.
*
* <p class="note"><strong>Note:</strong>
* Use of this class requires the {@link android.Manifest.permission#NFC}
* permission.
*/
public final class NdefFormatable extends BasicTagTechnology {
+ private static final String TAG = "NFC";
+
+ /**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static NdefFormatable get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.NDEF_FORMATABLE)) return null;
+ try {
+ return new NdefFormatable(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
/**
* Internal constructor, to be used by NfcAdapter
* @hide
*/
- public NdefFormatable(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
- super(adapter, tag, tech);
+ public NdefFormatable(Tag tag) throws RemoteException {
+ super(tag, TagTechnology.NDEF_FORMATABLE);
}
/**
@@ -52,10 +70,9 @@
checkConnected();
try {
- byte[] DEFAULT_KEY = {(byte)0xFF,(byte)0xFF,(byte)0xFF,
- (byte)0xFF,(byte)0xFF,(byte)0xFF};
int serviceHandle = mTag.getServiceHandle();
- int errorCode = mTagService.formatNdef(serviceHandle, DEFAULT_KEY);
+ INfcTag tagService = mTag.getTagService();
+ int errorCode = tagService.formatNdef(serviceHandle, MifareClassic.KEY_DEFAULT);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
@@ -68,8 +85,8 @@
throw new IOException();
}
// Now check and see if the format worked
- if (mTagService.isNdef(serviceHandle)) {
- errorCode = mTagService.ndefWrite(serviceHandle, firstMessage);
+ if (tagService.isNdef(serviceHandle)) {
+ errorCode = tagService.ndefWrite(serviceHandle, firstMessage);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
@@ -85,14 +102,7 @@
throw new IOException();
}
} catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
+ Log.e(TAG, "NFC service dead", e);
}
}
-
- @Override
- public byte[] transceive(byte[] data) {
- checkConnected();
-
- throw new UnsupportedOperationException();
- }
}
diff --git a/core/java/android/nfc/tech/NfcA.java b/core/java/android/nfc/tech/NfcA.java
new file mode 100644
index 0000000..24badc4
--- /dev/null
+++ b/core/java/android/nfc/tech/NfcA.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import java.io.IOException;
+
+/**
+ * A low-level connection to a {@link Tag} using the NFC-A technology, also known as
+ * ISO1443-3A.
+ *
+ * <p>You can acquire this kind of connection with {@link #get}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * <p>Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class NfcA extends BasicTagTechnology {
+ /** @hide */
+ public static final String EXTRA_SAK = "sak";
+ /** @hide */
+ public static final String EXTRA_ATQA = "atqa";
+
+ private short mSak;
+ private byte[] mAtqa;
+
+ /**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static NfcA get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.NFC_A)) return null;
+ try {
+ return new NfcA(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public NfcA(Tag tag) throws RemoteException {
+ super(tag, TagTechnology.NFC_A);
+ Bundle extras = tag.getTechExtras(TagTechnology.NFC_A);
+ mSak = extras.getShort(EXTRA_SAK);
+ mAtqa = extras.getByteArray(EXTRA_ATQA);
+ }
+
+ /**
+ * Returns the ATQA/SENS_RES bytes discovered at tag discovery.
+ */
+ public byte[] getAtqa() {
+ return mAtqa;
+ }
+
+ /**
+ * Returns the SAK/SEL_RES discovered at tag discovery.
+ */
+ public short getSak() {
+ return mSak;
+ }
+
+ /**
+ * Send data to a tag and receive the response.
+ * <p>
+ * This method will block until the response is received. It can be canceled
+ * with {@link #close}.
+ * <p>Requires {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param data bytes to send
+ * @return bytes received in response
+ * @throws IOException if the target is lost or connection closed
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
+}
diff --git a/core/java/android/nfc/technology/NfcB.java b/core/java/android/nfc/tech/NfcB.java
similarity index 60%
rename from core/java/android/nfc/technology/NfcB.java
rename to core/java/android/nfc/tech/NfcB.java
index 267c94d..abeef32 100644
--- a/core/java/android/nfc/technology/NfcB.java
+++ b/core/java/android/nfc/tech/NfcB.java
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-package android.nfc.technology;
+package android.nfc.tech;
-import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
+import java.io.IOException;
+
/**
* A low-level connection to a {@link Tag} using the NFC-B technology, also known as
* ISO1443-3B.
*
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * <p>You can acquire this kind of connection with {@link #get}.
* Use this class to send and receive data with {@link #transceive transceive()}.
*
* <p>Applications must implement their own protocol stack on top of
@@ -44,9 +45,25 @@
private byte[] mAppData;
private byte[] mProtInfo;
- public NfcB(NfcAdapter adapter, Tag tag, Bundle extras)
- throws RemoteException {
- super(adapter, tag, TagTechnology.NFC_B);
+ /**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static NfcB get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.NFC_B)) return null;
+ try {
+ return new NfcB(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public NfcB(Tag tag) throws RemoteException {
+ super(tag, TagTechnology.NFC_B);
+ Bundle extras = tag.getTechExtras(TagTechnology.NFC_B);
mAppData = extras.getByteArray(EXTRA_APPDATA);
mProtInfo = extras.getByteArray(EXTRA_PROTINFO);
}
@@ -67,4 +84,18 @@
return mProtInfo;
}
+ /**
+ * Send data to a tag and receive the response.
+ * <p>
+ * This method will block until the response is received. It can be canceled
+ * with {@link #close}.
+ * <p>Requires {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param data bytes to send
+ * @return bytes received in response
+ * @throws IOException if the target is lost or connection closed
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
}
diff --git a/core/java/android/nfc/tech/NfcF.java b/core/java/android/nfc/tech/NfcF.java
new file mode 100644
index 0000000..f617739
--- /dev/null
+++ b/core/java/android/nfc/tech/NfcF.java
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import java.io.IOException;
+
+/**
+ * A low-level connection to a {@link Tag} using the NFC-F technology, also known as
+ * JIS6319-4.
+ *
+ * <p>You can acquire this kind of connection with {@link #get}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * <p>Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class NfcF extends BasicTagTechnology {
+ /** @hide */
+ public static final String EXTRA_SC = "systemcode";
+ /** @hide */
+ public static final String EXTRA_PMM = "pmm";
+
+ private byte[] mSystemCode = null;
+ private byte[] mManufacturer = null;
+
+ /**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static NfcF get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.NFC_F)) return null;
+ try {
+ return new NfcF(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public NfcF(Tag tag) throws RemoteException {
+ super(tag, TagTechnology.NFC_F);
+ Bundle extras = tag.getTechExtras(TagTechnology.NFC_F);
+ if (extras != null) {
+ mSystemCode = extras.getByteArray(EXTRA_SC);
+ mManufacturer = extras.getByteArray(EXTRA_PMM);
+ }
+ }
+
+ public byte[] getSystemCode() {
+ return mSystemCode;
+ }
+
+ public byte[] getManufacturer() {
+ return mManufacturer;
+ }
+
+ /**
+ * Send data to a tag and receive the response.
+ * <p>
+ * This method will block until the response is received. It can be canceled
+ * with {@link #close}.
+ * <p>Requires {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param data bytes to send
+ * @return bytes received in response
+ * @throws IOException if the target is lost or connection closed
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
+}
diff --git a/core/java/android/nfc/tech/NfcV.java b/core/java/android/nfc/tech/NfcV.java
new file mode 100644
index 0000000..8e1f066
--- /dev/null
+++ b/core/java/android/nfc/tech/NfcV.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import java.io.IOException;
+
+/**
+ * A low-level connection to a {@link Tag} using NFC vicinity technology, also known as
+ * ISO15693.
+ *
+ * <p>You can acquire this kind of connection with {@link #get}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * <p>Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class NfcV extends BasicTagTechnology {
+ /** @hide */
+ public static final String EXTRA_RESP_FLAGS = "respflags";
+
+ /** @hide */
+ public static final String EXTRA_DSFID = "dsfid";
+
+ private byte mRespFlags;
+ private byte mDsfId;
+
+ /**
+ * Returns an instance of this tech for the given tag. If the tag doesn't support
+ * this tech type null is returned.
+ *
+ * @param tag The tag to get the tech from
+ */
+ public static NfcV get(Tag tag) {
+ if (!tag.hasTech(TagTechnology.NFC_V)) return null;
+ try {
+ return new NfcV(tag);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /** @hide */
+ public NfcV(Tag tag) throws RemoteException {
+ super(tag, TagTechnology.NFC_V);
+ Bundle extras = tag.getTechExtras(TagTechnology.NFC_V);
+ mRespFlags = extras.getByte(EXTRA_RESP_FLAGS);
+ mDsfId = extras.getByte(EXTRA_DSFID);
+ }
+
+ public byte getResponseFlags() {
+ return mRespFlags;
+ }
+
+ public byte getDsfId() {
+ return mDsfId;
+ }
+
+ /**
+ * Send data to a tag and receive the response.
+ * <p>
+ * This method will block until the response is received. It can be canceled
+ * with {@link #close}.
+ * <p>Requires {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param data bytes to send
+ * @return bytes received in response
+ * @throws IOException if the target is lost or connection closed
+ */
+ public byte[] transceive(byte[] data) throws IOException {
+ return transceive(data, true);
+ }
+}
diff --git a/core/java/android/nfc/tech/TagTechnology.java b/core/java/android/nfc/tech/TagTechnology.java
new file mode 100644
index 0000000..c8ccdcf
--- /dev/null
+++ b/core/java/android/nfc/tech/TagTechnology.java
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+package android.nfc.tech;
+
+import android.nfc.Tag;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+public interface TagTechnology extends Closeable {
+ /**
+ * This technology is an instance of {@link NfcA}.
+ * <p>Support for this technology type is mandatory.
+ * @hide
+ */
+ public static final int NFC_A = 1;
+
+ /**
+ * This technology is an instance of {@link NfcB}.
+ * <p>Support for this technology type is mandatory.
+ * @hide
+ */
+ public static final int NFC_B = 2;
+
+ /**
+ * This technology is an instance of {@link IsoDep}.
+ * <p>Support for this technology type is mandatory.
+ * @hide
+ */
+ public static final int ISO_DEP = 3;
+
+ /**
+ * This technology is an instance of {@link NfcF}.
+ * <p>Support for this technology type is mandatory.
+ * @hide
+ */
+ public static final int NFC_F = 4;
+
+ /**
+ * This technology is an instance of {@link NfcV}.
+ * <p>Support for this technology type is mandatory.
+ * @hide
+ */
+ public static final int NFC_V = 5;
+
+ /**
+ * This technology is an instance of {@link Ndef}.
+ * <p>Support for this technology type is mandatory.
+ * @hide
+ */
+ public static final int NDEF = 6;
+
+ /**
+ * This technology is an instance of {@link NdefFormatable}.
+ * <p>Support for this technology type is mandatory.
+ * @hide
+ */
+ public static final int NDEF_FORMATABLE = 7;
+
+ /**
+ * This technology is an instance of {@link MifareClassic}.
+ * <p>Support for this technology type is optional. If a stack doesn't support this technology
+ * type tags using it must still be discovered and present the lower level radio interface
+ * technologies in use.
+ * @hide
+ */
+ public static final int MIFARE_CLASSIC = 8;
+
+ /**
+ * This technology is an instance of {@link MifareUltralight}.
+ * <p>Support for this technology type is optional. If a stack doesn't support this technology
+ * type tags using it must still be discovered and present the lower level radio interface
+ * technologies in use.
+ * @hide
+ */
+ public static final int MIFARE_ULTRALIGHT = 9;
+
+ /**
+ * Get the {@link Tag} object this technology came from.
+ */
+ public Tag getTag();
+
+ /**
+ * Opens a connection to the {@link Tag} enabling interactive commands. The command set
+ * varies by the technology type.
+ *
+ * <p>This method blocks until the connection has been established.
+ *
+ * <p>A call to {@link #close} from another thread will cancel a blocked call and cause an
+ * IOException to be thrown on the thread that is blocked.
+ *
+ * @see #reconnect()
+ * @see #close()
+ * @throws IOException if the target is lost, or connect canceled
+ */
+ public void connect() throws IOException;
+
+ /**
+ * Re-connect to the {@link Tag} associated with this connection. Reconnecting to a tag can be
+ * used to reset the state of the tag itself.
+ *
+ * <p>This method blocks until the connection is re-established.
+ *
+ * <p>A call to {@link #close} from another thread will cancel a blocked call and cause an
+ * IOException to be thrown on the thread that is blocked.
+ *
+ * @see #connect()
+ * @see #close()
+ * @throws IOException
+ */
+ public void reconnect() throws IOException;
+
+ /**
+ * Closes the connection to the {@link Tag}. This call is non-blocking and causes all blocking
+ * operations such as {@link #connect} to be canceled and immediately throw
+ * {@link java.io.IOException} on the thread that is blocked.
+ *
+ * <p>
+ * Once this method is called, this object cannot be re-used and should be discarded. Further
+ * calls to {@link #connect} will fail.
+ *
+ * @see #connect()
+ * @see #reconnect()
+ */
+ public void close() throws IOException;
+}
diff --git a/core/java/android/nfc/technology/BasicTagTechnology.java b/core/java/android/nfc/technology/BasicTagTechnology.java
deleted file mode 100644
index 553f6ec..0000000
--- a/core/java/android/nfc/technology/BasicTagTechnology.java
+++ /dev/null
@@ -1,254 +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.
- */
-
-package android.nfc.technology;
-
-import java.io.IOException;
-
-import android.nfc.INfcAdapter;
-import android.nfc.INfcTag;
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.nfc.ErrorCodes;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * A base class for tag technologies that are built on top of transceive().
- */
-/* package */ abstract class BasicTagTechnology implements TagTechnology {
-
- /*package*/ final Tag mTag;
- /*package*/ boolean mIsConnected;
- /*package*/ int mSelectedTechnology;
- private final NfcAdapter mAdapter;
-
- // Following fields are final after construction, except for
- // during attemptDeadServiceRecovery() when NFC crashes.
- // Not locked - we accept a best effort attempt when NFC crashes.
- /*package*/ INfcAdapter mService;
- /*package*/ INfcTag mTagService;
-
- private static final String TAG = "NFC";
-
- /**
- * @hide
- */
- public BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException {
- int[] techList = tag.getTechnologyList();
- int i;
-
- // Check target validity
- for (i = 0; i < techList.length; i++) {
- if (tech == techList[i]) {
- break;
- }
- }
- if (i >= techList.length) {
- // Technology not found
- throw new IllegalArgumentException("Technology " + tech + " not present on tag " + tag);
- }
-
- mAdapter = adapter;
- mService = mAdapter.getService();
- try {
- mTagService = mService.getNfcTagInterface();
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- }
- mTag = tag;
- mSelectedTechnology = tech;
- }
-
- /**
- * @hide
- */
- public BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException {
- this(adapter, tag, tag.getTechnologyList()[0]);
- }
-
- /** NFC service dead - attempt best effort recovery */
- /*package*/ void attemptDeadServiceRecovery(Exception e) {
- mAdapter.attemptDeadServiceRecovery(e);
- /* assigning to mService is not thread-safe, but this is best-effort code
- * and on a well-behaved system should never happen */
- mService = mAdapter.getService();
- try {
- mTagService = mService.getNfcTagInterface();
- } catch (RemoteException e2) {
- Log.e(TAG, "second RemoteException trying to recover from dead NFC service", e2);
- }
- }
-
- /**
- * Get the {@link Tag} this connection is associated with.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- */
- @Override
- public Tag getTag() {
- return mTag;
- }
-
- public void checkConnected() {
- if ((mTag.getConnectedTechnology() != getTechnologyId()) ||
- (mTag.getConnectedTechnology() == -1)) {
- throw new IllegalStateException("Call connect() first!");
- }
- }
-
- /**
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- */
- @Override
- public int getTechnologyId() {
- return mSelectedTechnology;
- }
-
- /**
- * Helper to indicate if {@link #transceive transceive()} calls might succeed.
- * <p>
- * Does not cause RF activity, and does not block.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed
- * to be within range. Applications must still handle {@link java.io.IOException}
- * while using {@link #transceive transceive()}, in case connection is lost after this method
- * returns true.
- */
- public boolean isConnected() {
- if (!mIsConnected) {
- return false;
- }
-
- try {
- return mTagService.isPresent(mTag.getServiceHandle());
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return false;
- }
- }
-
- /**
- * Connect to the {@link Tag} associated with this connection.
- * <p>
- * This method blocks until the connection is established.
- * <p>
- * {@link #close} can be called from another thread to cancel this connection
- * attempt.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- * @throws IOException if the target is lost, or connect canceled
- */
- @Override
- public void connect() throws IOException {
- try {
- int errorCode = mTagService.connect(mTag.getServiceHandle(), getTechnologyId());
-
- if (errorCode == ErrorCodes.SUCCESS) {
- // Store this in the tag object
- mTag.setConnectedTechnology(getTechnologyId());
- mIsConnected = true;
- } else {
- throw new IOException();
- }
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- throw new IOException("NFC service died");
- }
- }
-
- /**
- * Re-connect to the {@link Tag} associated with this connection.
- * <p>
- * Reconnecting to a tag can be used to reset the state of the tag itself.
- * This method blocks until the connection is re-established.
- * <p>
- * {@link #close} can be called from another thread to cancel this connection
- * attempt.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- * @throws IOException if the target is lost, or connect canceled
- */
- @Override
- public void reconnect() throws IOException {
- if (!mIsConnected) {
- throw new IllegalStateException("Technology not connected yet");
- } else {
- try {
- int errorCode = mTagService.reconnect(mTag.getServiceHandle());
-
- if (errorCode != ErrorCodes.SUCCESS) {
- mIsConnected = false;
- mTag.setTechnologyDisconnected();
- throw new IOException();
- }
- } catch (RemoteException e) {
- mIsConnected = false;
- mTag.setTechnologyDisconnected();
- attemptDeadServiceRecovery(e);
- throw new IOException("NFC service died");
- }
- }
- }
-
- /**
- * Close this connection.
- * <p>
- * Causes blocking operations such as {@link #transceive transceive()} or {@link #connect} to
- * be canceled and immediately throw {@link java.io.IOException}.
- * <p>
- * Once this method is called, this object cannot be re-used and should be discarded. Further
- * calls to {@link #transceive transceive()} or {@link #connect} will fail.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- */
- @Override
- public void close() {
- try {
- /* Note that we don't want to physically disconnect the tag,
- * but just reconnect to it to reset its state
- */
- mTagService.reconnect(mTag.getServiceHandle());
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- } finally {
- mIsConnected = false;
- mTag.setTechnologyDisconnected();
- }
- }
-
- /**
- * Send data to a tag and receive the response.
- * <p>
- * This method will block until the response is received. It can be canceled
- * with {@link #close}.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- *
- * @param data bytes to send
- * @return bytes received in response
- * @throws IOException if the target is lost or connection closed
- */
- public byte[] transceive(byte[] data) throws IOException {
- checkConnected();
-
- try {
- byte[] response = mTagService.transceive(mTag.getServiceHandle(), data, true);
- if (response == null) {
- throw new IOException("transceive failed");
- }
- return response;
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- throw new IOException("NFC service died");
- }
- }
-}
diff --git a/core/java/android/nfc/technology/IsoDep.java b/core/java/android/nfc/technology/IsoDep.java
deleted file mode 100644
index 32a7542..0000000
--- a/core/java/android/nfc/technology/IsoDep.java
+++ /dev/null
@@ -1,67 +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.
- */
-
-package android.nfc.technology;
-
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-import java.io.IOException;
-
-/**
- * A low-level connection to a {@link Tag} using the ISO-DEP technology, also known as
- * ISO1443-4.
- *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
- * Use this class to send and receive data with {@link #transceive transceive()}.
- *
- * <p>Applications must implement their own protocol stack on top of
- * {@link #transceive transceive()}.
- *
- * <p class="note"><strong>Note:</strong>
- * Use of this class requires the {@link android.Manifest.permission#NFC}
- * permission.
- */
-public final class IsoDep extends BasicTagTechnology {
- /** @hide */
- public static final String EXTRA_HI_LAYER_RESP = "hiresp";
- /** @hide */
- public static final String EXTRA_HIST_BYTES = "histbytes";
-
- private byte[] mHiLayerResponse = null;
- private byte[] mHistBytes = null;
-
- public IsoDep(NfcAdapter adapter, Tag tag, Bundle extras)
- throws RemoteException {
- super(adapter, tag, TagTechnology.ISO_DEP);
- if (extras != null) {
- mHiLayerResponse = extras.getByteArray(EXTRA_HI_LAYER_RESP);
- mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES);
- }
- }
-
- /**
- * 3A only
- */
- public byte[] getHistoricalBytes() { return mHistBytes; }
-
- /**
- * 3B only
- */
- public byte[] getHiLayerResponse() { return mHiLayerResponse; }
-}
diff --git a/core/java/android/nfc/technology/MifareClassic.java b/core/java/android/nfc/technology/MifareClassic.java
deleted file mode 100644
index 799f0a78..0000000
--- a/core/java/android/nfc/technology/MifareClassic.java
+++ /dev/null
@@ -1,404 +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.
- */
-
-package android.nfc.technology;
-
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-import java.io.IOException;
-
-/**
- * Concrete class for TagTechnology.MIFARE_CLASSIC
- *
- * Mifare classic has n sectors, with varying sizes, although
- * they are at least the same pattern for any one mifare classic
- * product. Each sector has two keys. Authentication with the correct
- * key is needed before access to any sector.
- *
- * Each sector has k blocks.
- * Block size is constant across the whole mifare classic family.
- */
-public final class MifareClassic extends BasicTagTechnology {
- /**
- * The well-known, default MIFARE read key.
- * Use this key to effectively make the payload in this sector
- * public.
- */
- public static final byte[] KEY_DEFAULT =
- {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
- /**
- * The well-known, default Mifare Application Directory read key.
- */
- public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY =
- {(byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5};
- /**
- * The well-known, default read key for NDEF data on a Mifare Classic
- */
- public static final byte[] KEY_NFC_FORUM =
- {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
-
- public static final int TYPE_CLASSIC = 0;
- public static final int TYPE_PLUS = 1;
- public static final int TYPE_PRO = 2;
- public static final int TYPE_DESFIRE = 3;
- public static final int TYPE_ULTRALIGHT = 4;
- public static final int TYPE_UNKNOWN = 5;
-
- public static final int SIZE_1K = 1024;
- public static final int SIZE_2K = 2048;
- public static final int SIZE_4K = 4096;
- public static final int SIZE_MINI = 320;
- public static final int SIZE_UNKNOWN = 0;
-
- private boolean mIsEmulated;
- private int mType;
- private int mSize;
-
- public MifareClassic(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
- super(adapter, tag, TagTechnology.MIFARE_CLASSIC);
-
- // Check if this could actually be a Mifare
- NfcA a = (NfcA) tag.getTechnology(adapter, TagTechnology.NFC_A);
- //short[] ATQA = getATQA(tag);
-
- mIsEmulated = false;
- mType = TYPE_UNKNOWN;
- mSize = SIZE_UNKNOWN;
-
- switch (a.getSak()) {
- case 0x00:
- // could be UL or UL-C
- mType = TYPE_ULTRALIGHT;
- break;
- case 0x08:
- // Type == classic
- // Size = 1K
- mType = TYPE_CLASSIC;
- mSize = SIZE_1K;
- break;
- case 0x09:
- // Type == classic mini
- // Size == ?
- mType = TYPE_CLASSIC;
- mSize = SIZE_MINI;
- break;
- case 0x10:
- // Type == MF+
- // Size == 2K
- // SecLevel = SL2
- mType = TYPE_PLUS;
- mSize = SIZE_2K;
- break;
- case 0x11:
- // Type == MF+
- // Size == 4K
- // Seclevel = SL2
- mType = TYPE_PLUS;
- mSize = SIZE_4K;
- break;
- case 0x18:
- // Type == classic
- // Size == 4k
- mType = TYPE_CLASSIC;
- mSize = SIZE_4K;
- break;
- case 0x20:
- // TODO this really should be a short, not byte
- if (a.getAtqa()[0] == 0x03) {
- // Type == DESFIRE
- mType = TYPE_DESFIRE;
- } else {
- // Type == MF+
- // SL = SL3
- mType = TYPE_PLUS;
- mSize = SIZE_UNKNOWN;
- }
- break;
- case 0x28:
- // Type == MF Classic
- // Size == 1K
- // Emulated == true
- mType = TYPE_CLASSIC;
- mSize = SIZE_1K;
- mIsEmulated = true;
- break;
- case 0x38:
- // Type == MF Classic
- // Size == 4K
- // Emulated == true
- mType = TYPE_CLASSIC;
- mSize = SIZE_4K;
- mIsEmulated = true;
- break;
- case 0x88:
- // Type == MF Classic
- // Size == 1K
- // NXP-tag: false
- mType = TYPE_CLASSIC;
- mSize = SIZE_1K;
- break;
- case 0x98:
- case 0xB8:
- // Type == MF Pro
- // Size == 4K
- mType = TYPE_PRO;
- mSize = SIZE_4K;
- break;
- default:
- // Unknown mifare
- mType = TYPE_UNKNOWN;
- mSize = SIZE_UNKNOWN;
- break;
- }
- }
-
- // Immutable data known at discovery time
- public int getSize() {
- return mSize;
- }
-
- public int getType() {
- return mType;
- }
-
- public boolean isEmulated() {
- return mIsEmulated;
- }
-
- public int getSectorCount() {
- switch (mSize) {
- case SIZE_1K: {
- return 16;
- }
- case SIZE_2K: {
- return 32;
- }
- case SIZE_4K: {
- return 40;
- }
- case SIZE_MINI: {
- return 5;
- }
- default: {
- return 0;
- }
- }
- }
-
- public int getSectorSize(int sector) {
- return getBlockCount(sector) * 16;
- }
-
- public int getTotalBlockCount() {
- int totalBlocks = 0;
- for (int sec = 0; sec < getSectorCount(); sec++) {
- totalBlocks += getSectorSize(sec);
- }
-
- return totalBlocks;
- }
-
- public int getBlockCount(int sector) {
- if (sector >= getSectorCount()) {
- throw new IllegalArgumentException("this card only has " + getSectorCount() +
- " sectors");
- }
-
- if (sector <= 32) {
- return 4;
- } else {
- return 16;
- }
- }
-
- private byte firstBlockInSector(int sector) {
- if (sector < 32) {
- return (byte) ((sector * 4) & 0xff);
- } else {
- return (byte) ((32 * 4 + ((sector - 32) * 16)) & 0xff);
- }
- }
-
- // Methods that require connect()
- /**
- * Authenticate for a given block.
- * Note that this will authenticate the entire sector the block belongs to.
- */
- public boolean authenticateBlock(int block, byte[] key, boolean keyA) {
- checkConnected();
-
- byte[] cmd = new byte[12];
-
- // First byte is the command
- if (keyA) {
- cmd[0] = 0x60; // phHal_eMifareAuthentA
- } else {
- cmd[0] = 0x61; // phHal_eMifareAuthentB
- }
-
- // Second byte is block address
- cmd[1] = (byte) block;
-
- // Next 4 bytes are last 4 bytes of UID
- byte[] uid = getTag().getId();
- System.arraycopy(uid, uid.length - 4, cmd, 2, 4);
-
- // Next 6 bytes are key
- System.arraycopy(key, 0, cmd, 6, 6);
-
- try {
- if ((transceive(cmd) != null)) {
- return true;
- }
- } catch (IOException e) {
- // No need to deal with, will return false anyway
- }
- return false;
- }
-
- /**
- * Authenticate for a given sector.
- */
- public boolean authenticateSector(int sector, byte[] key, boolean keyA) {
- checkConnected();
-
- byte addr = (byte) ((firstBlockInSector(sector)) & 0xff);
-
- // Note that authenticating a block of a sector, will authenticate
- // the entire sector.
- return authenticateBlock(addr, key, keyA);
- }
-
- /**
- * Sector indexing starts at 0.
- * Block indexing starts at 0, and resets in each sector.
- * @throws IOException
- */
- public byte[] readBlock(int sector, int block) throws IOException {
- checkConnected();
-
- byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
- return readBlock(addr);
-
- }
-
- /**
- * Reads absolute block index.
- * @throws IOException
- */
- public byte[] readBlock(int block) throws IOException {
- checkConnected();
-
- byte addr = (byte) block;
- byte[] blockread_cmd = { 0x30, addr };
-
- return transceive(blockread_cmd);
- }
-
- /**
- * Writes absolute block index.
- * @throws IOException
- */
- public void writeBlock(int block, byte[] data) throws IOException {
- checkConnected();
-
- byte addr = (byte) block;
- byte[] blockwrite_cmd = new byte[data.length + 2];
- blockwrite_cmd[0] = (byte) 0xA0; // MF write command
- blockwrite_cmd[1] = addr;
- System.arraycopy(data, 0, blockwrite_cmd, 2, data.length);
-
- transceive(blockwrite_cmd);
- }
-
- /**
- * Writes relative block in sector.
- * @throws IOException
- */
- public void writeBlock(int sector, int block, byte[] data) throws IOException {
- checkConnected();
-
- byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
-
- writeBlock(addr, data);
- }
-
- public void increment(int block) throws IOException {
- checkConnected();
-
- byte addr = (byte) block;
- byte[] incr_cmd = { (byte) 0xC1, (byte) block };
-
- transceive(incr_cmd);
- }
-
- public void decrement(int block) throws IOException {
- checkConnected();
-
- byte addr = (byte) block;
- byte[] decr_cmd = { (byte) 0xC0, (byte) block };
-
- transceive(decr_cmd);
- }
-
- public void transfer(int block) throws IOException {
- checkConnected();
-
- byte addr = (byte) block;
- byte[] trans_cmd = { (byte) 0xB0, (byte) block };
-
- transceive(trans_cmd);
- }
-
- public void restore(int block) throws IOException {
- checkConnected();
-
- byte addr = (byte) block;
- byte[] rest_cmd = { (byte) 0xC2, (byte) block };
-
- transceive(rest_cmd);
- }
-
- /**
- * Send data to a tag and receive the response.
- * <p>
- * This method will block until the response is received. It can be canceled
- * with {@link #close}.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- *
- * @param data bytes to send
- * @return bytes received in response
- * @throws IOException if the target is lost or connection closed
- */
- @Override
- public byte[] transceive(byte[] data) throws IOException {
- checkConnected();
-
- try {
- byte[] response = mTagService.transceive(mTag.getServiceHandle(), data, false);
- if (response == null) {
- throw new IOException("transceive failed");
- }
- return response;
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- throw new IOException("NFC service died");
- }
- }
-}
diff --git a/core/java/android/nfc/technology/MifareUltralight.java b/core/java/android/nfc/technology/MifareUltralight.java
deleted file mode 100644
index 7103b4d..0000000
--- a/core/java/android/nfc/technology/MifareUltralight.java
+++ /dev/null
@@ -1,133 +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.
- */
-
-package android.nfc.technology;
-
-import java.io.IOException;
-
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-/**
- * Concrete class for TagTechnology.MIFARE_ULTRALIGHT
- *
- * Mifare classic has n sectors, with varying sizes, although
- * they are at least the same pattern for any one mifare classic
- * product. Each sector has two keys. Authentication with the correct
- * key is needed before access to any sector.
- *
- * Each sector has k blocks.
- * Block size is constant across the whole mifare classic family.
- */
-public final class MifareUltralight extends BasicTagTechnology {
- public static final int TYPE_ULTRALIGHT = 1;
- public static final int TYPE_ULTRALIGHT_C = 2;
- public static final int TYPE_UNKNOWN = 10;
-
- private static final int NXP_MANUFACTURER_ID = 0x04;
-
- private int mType;
-
- public MifareUltralight(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
- super(adapter, tag, TagTechnology.MIFARE_ULTRALIGHT);
-
- // Check if this could actually be a Mifare
- NfcA a = (NfcA) tag.getTechnology(adapter, TagTechnology.NFC_A);
-
- mType = TYPE_UNKNOWN;
-
- if( a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID ) {
- // could be UL or UL-C
- mType = TYPE_ULTRALIGHT;
- }
- }
-
- public int getType() {
- return mType;
- }
-
- // Methods that require connect()
- /**
- * @throws IOException
- */
- public byte[] readBlock(int block) throws IOException {
- checkConnected();
-
- byte[] blockread_cmd = { 0x30, (byte)block }; // phHal_eMifareRead
- return transceive(blockread_cmd);
- }
-
- /**
- * @throws IOException
- */
- public byte[] readOTP() throws IOException {
- checkConnected();
-
- return readBlock(3); // OTP is at page 3
- }
-
- public void writePage(int block, byte[] data) throws IOException {
- checkConnected();
-
- byte[] pagewrite_cmd = new byte[data.length + 2];
- pagewrite_cmd[0] = (byte) 0xA2;
- pagewrite_cmd[1] = (byte) block;
- System.arraycopy(data, 0, pagewrite_cmd, 2, data.length);
-
- transceive(pagewrite_cmd);
- }
-
- public void writeBlock(int block, byte[] data) throws IOException {
- checkConnected();
-
- byte[] blockwrite_cmd = new byte[data.length + 2];
- blockwrite_cmd[0] = (byte) 0xA0;
- blockwrite_cmd[1] = (byte) block;
- System.arraycopy(data, 0, blockwrite_cmd, 2, data.length);
-
- transceive(blockwrite_cmd);
- }
-
- /**
- * Send data to a tag and receive the response.
- * <p>
- * This method will block until the response is received. It can be canceled
- * with {@link #close}.
- * <p>Requires {@link android.Manifest.permission#NFC} permission.
- *
- * @param data bytes to send
- * @return bytes received in response
- * @throws IOException if the target is lost or connection closed
- */
- @Override
- public byte[] transceive(byte[] data) throws IOException {
- checkConnected();
-
- try {
- byte[] response = mTagService.transceive(mTag.getServiceHandle(), data, false);
- if (response == null) {
- throw new IOException("transceive failed");
- }
- return response;
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- throw new IOException("NFC service died");
- }
- }
-
-}
diff --git a/core/java/android/nfc/technology/NfcA.java b/core/java/android/nfc/technology/NfcA.java
deleted file mode 100644
index ef46762..0000000
--- a/core/java/android/nfc/technology/NfcA.java
+++ /dev/null
@@ -1,66 +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.
- */
-
-package android.nfc.technology;
-
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-/**
- * A low-level connection to a {@link Tag} using the NFC-A technology, also known as
- * ISO1443-3A.
- *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
- * Use this class to send and receive data with {@link #transceive transceive()}.
- *
- * <p>Applications must implement their own protocol stack on top of
- * {@link #transceive transceive()}.
- *
- * <p class="note"><strong>Note:</strong>
- * Use of this class requires the {@link android.Manifest.permission#NFC}
- * permission.
- */
-public final class NfcA extends BasicTagTechnology {
- /** @hide */
- public static final String EXTRA_SAK = "sak";
- /** @hide */
- public static final String EXTRA_ATQA = "atqa";
-
- private short mSak;
- private byte[] mAtqa;
-
- public NfcA(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
- super(adapter, tag, TagTechnology.NFC_A);
- mSak = extras.getShort(EXTRA_SAK);
- mAtqa = extras.getByteArray(EXTRA_ATQA);
- }
-
- /**
- * Returns the ATQA/SENS_RES bytes discovered at tag discovery.
- */
- public byte[] getAtqa() {
- return mAtqa;
- }
-
- /**
- * Returns the SAK/SEL_RES discovered at tag discovery.
- */
- public short getSak() {
- return mSak;
- }
-}
diff --git a/core/java/android/nfc/technology/NfcF.java b/core/java/android/nfc/technology/NfcF.java
deleted file mode 100644
index 6741ac8..0000000
--- a/core/java/android/nfc/technology/NfcF.java
+++ /dev/null
@@ -1,63 +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.
- */
-
-package android.nfc.technology;
-
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-/**
- * A low-level connection to a {@link Tag} using the NFC-F technology, also known as
- * JIS6319-4.
- *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
- * Use this class to send and receive data with {@link #transceive transceive()}.
- *
- * <p>Applications must implement their own protocol stack on top of
- * {@link #transceive transceive()}.
- *
- * <p class="note"><strong>Note:</strong>
- * Use of this class requires the {@link android.Manifest.permission#NFC}
- * permission.
- */
-public final class NfcF extends BasicTagTechnology {
- /** @hide */
- public static final String EXTRA_SC = "systemcode";
- /** @hide */
- public static final String EXTRA_PMM = "pmm";
-
- private byte[] mSystemCode = null;
- private byte[] mManufacturer = null;
-
- public NfcF(NfcAdapter adapter, Tag tag, Bundle extras)
- throws RemoteException {
- super(adapter, tag, TagTechnology.NFC_F);
- if (extras != null) {
- mSystemCode = extras.getByteArray(EXTRA_SC);
- mManufacturer = extras.getByteArray(EXTRA_PMM);
- }
- }
-
- public byte[] getSystemCode() {
- return mSystemCode;
- }
-
- public byte[] getManufacturer() {
- return mManufacturer;
- }
-}
diff --git a/core/java/android/nfc/technology/NfcV.java b/core/java/android/nfc/technology/NfcV.java
deleted file mode 100644
index 460de6a..0000000
--- a/core/java/android/nfc/technology/NfcV.java
+++ /dev/null
@@ -1,62 +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.
- */
-
-package android.nfc.technology;
-
-import android.nfc.NfcAdapter;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-/**
- * A low-level connection to a {@link Tag} using the NFC-V technology, also known as
- * ISO15693.
- *
- * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
- * Use this class to send and receive data with {@link #transceive transceive()}.
- *
- * <p>Applications must implement their own protocol stack on top of
- * {@link #transceive transceive()}.
- *
- * <p class="note"><strong>Note:</strong>
- * Use of this class requires the {@link android.Manifest.permission#NFC}
- * permission.
- */
-public final class NfcV extends BasicTagTechnology {
- /** @hide */
- public static final String EXTRA_RESP_FLAGS = "respflags";
-
- /** @hide */
- public static final String EXTRA_DSFID = "dsfid";
-
- private byte mRespFlags;
- private byte mDsfId;
-
- public NfcV(NfcAdapter adapter, Tag tag, Bundle extras)
- throws RemoteException {
- super(adapter, tag, TagTechnology.NFC_V);
- mRespFlags = extras.getByte(EXTRA_RESP_FLAGS);
- mDsfId = extras.getByte(EXTRA_DSFID);
- }
-
- public byte getResponseFlags() {
- return mRespFlags;
- }
-
- public byte getDsfId() {
- return mDsfId;
- }
-}
diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java
deleted file mode 100644
index 62216c1..0000000
--- a/core/java/android/nfc/technology/TagTechnology.java
+++ /dev/null
@@ -1,94 +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.
- */
-
-package android.nfc.technology;
-
-import android.nfc.Tag;
-
-import java.io.IOException;
-
-public interface TagTechnology {
- /**
- * This object is an instance of {@link NfcA}
- */
- public static final int NFC_A = 1;
-
- /**
- * This object is an instance of {@link NfcB}
- */
- public static final int NFC_B = 2;
-
- /**
- * This object is an instance of {@link IsoDep}
- */
- public static final int ISO_DEP = 3;
-
- /**
- * This object is an instance of {@link NfcF}
- */
- public static final int NFC_F = 4;
-
- /**
- * This object is an instance of {@link NfcV}
- */
- public static final int NFC_V = 5;
-
- /**
- * This object is an instance of {@link Ndef}
- */
- public static final int NDEF = 6;
-
- /**
- * This object is an instance of {@link NdefFormatable}
- */
- public static final int NDEF_FORMATABLE = 7;
-
- /**
- * This object is an instance of {@link MifareClassic}
- */
- public static final int MIFARE_CLASSIC = 8;
-
- /**
- * This object is an instance of {@link MifareUltralight}
- */
- public static final int MIFARE_ULTRALIGHT = 9;
-
- /**
- * Returns the technology type for this tag connection.
- */
- public int getTechnologyId();
-
- /**
- * Get the backing tag object.
- */
- public Tag getTag();
-
- /**
- * @throws IOException
- */
- public void connect() throws IOException;
-
- /**
- * @throws IOException
- */
- public void reconnect() throws IOException;
-
- /**
- * Non-blocking. Immediately causes all blocking calls
- * to throw IOException.
- */
- public void close();
-}
diff --git a/core/java/android/nfc/technology/package.html b/core/java/android/nfc/technology/package.html
deleted file mode 100644
index 26b8a32..0000000
--- a/core/java/android/nfc/technology/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<HTML>
-<BODY>
-{@hide}
-</BODY>
-</HTML>
\ No newline at end of file
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index c46d2c5..6d7b7ce 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -512,10 +512,17 @@
Intent intent = new Intent("android.intent.action.START_TTS_SERVICE");
intent.addCategory("android.intent.category.TTS");
- mContext.bindService(intent, mServiceConnection,
- Context.BIND_AUTO_CREATE);
- // TODO handle case where the binding works (should always work) but
- // the plugin fails
+ boolean bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
+ if (!bound) {
+ Log.e("TextToSpeech.java", "initTts() failed to bind to service");
+ if (mInitListener != null) {
+ mInitListener.onInit(ERROR);
+ }
+ } else {
+ // initialization listener will be called inside ServiceConnection
+ Log.i("TextToSpeech.java", "initTts() successfully bound to service");
+ }
+ // TODO handle plugin failures
}
@@ -765,8 +772,9 @@
{
synchronized (mStartLock) {
int result = ERROR;
- Log.i("TTS", "speak() queueMode=" + queueMode);
+ Log.i("TextToSpeech.java - speak", "speak text of length " + text.length());
if (!mStarted) {
+ Log.e("TextToSpeech.java - speak", "service isn't started");
return result;
}
try {
@@ -1264,10 +1272,13 @@
*/
public int synthesizeToFile(String text, HashMap<String,String> params,
String filename) {
- Log.i("TTS", "synthesizeToFile()");
+ Log.i("TextToSpeech.java", "synthesizeToFile()");
synchronized (mStartLock) {
int result = ERROR;
+ Log.i("TextToSpeech.java - synthesizeToFile", "synthesizeToFile text of length "
+ + text.length());
if (!mStarted) {
+ Log.e("TextToSpeech.java - synthesizeToFile", "service isn't started");
return result;
}
try {
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index 4d83891..8f491ef 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -21,7 +21,100 @@
import android.os.Parcel;
import android.os.Parcelable;
-/** !!! TODO: real docs */
+//TODO: Improve Javadoc
+/**
+ * Represents an event that is sent out by the system at various times during a drag and drop
+ * operation. It is a complex data structure that contains several important pieces of data about
+ * the operation and the underlying data.
+ * <p>
+ * View objects that receive a DragEvent call {@link #getAction()}, which returns
+ * an action type that indicates the state of the drag and drop operation. This allows a View
+ * object to react to a change in state by changing its appearance or performing other actions.
+ * For example, a View can react to the {@link #ACTION_DRAG_ENTERED} action type by
+ * by changing one or more colors in its displayed image.
+ * </p>
+ * <p>
+ * During a drag and drop operation, the system displays an image that the user drags. This image
+ * is called a drag shadow. Several action types reflect the position of the drag shadow relative
+ * to the View receiving the event.
+ * </p>
+ * <p>
+ * Most methods return valid data only for certain event actions. This is summarized in the
+ * following table. Each possible {@link #getAction()} value is listed in the first column. The
+ * other columns indicate which method or methods return valid data for that getAction() value:
+ * </p>
+ * <table>
+ * <tr>
+ * <th scope="col">getAction() Value</th>
+ * <th scope="col">getClipDescription()</th>
+ * <th scope="col">getLocalState()</th>
+ * <th scope="col">getX()</th>
+ * <th scope="col">getY()</th>
+ * <th scope="col">getClipData()</th>
+ * <th scope="col">getResult()</th>
+ * </tr>
+ * <tr>
+ * <td>ACTION_DRAG_STARTED</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * </tr>
+ * <tr>
+ * <td>ACTION_DRAG_ENTERED</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * </tr>
+ * <tr>
+ * <td>ACTION_DRAG_LOCATION</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * </tr>
+ * <tr>
+ * <td>ACTION_DRAG_EXITED</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * </tr>
+ * <tr>
+ * <td>ACTION_DROP</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;"> </td>
+ * </tr>
+ * <tr>
+ * <td>ACTION_DRAG_ENDED</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;"> </td>
+ * <td style="text-align: center;">X</td>
+ * </tr>
+ * </table>
+ * <p>
+ * The {@link android.view.DragEvent#getAction()},
+ * {@link android.view.DragEvent#describeContents()},
+ * {@link android.view.DragEvent#writeToParcel(Parcel,int)}, and
+ * {@link android.view.DragEvent#toString()} methods always return valid data.
+ * </p>
+ */
public class DragEvent implements Parcelable {
private static final boolean TRACK_RECYCLED_LOCATION = false;
@@ -42,89 +135,113 @@
private static DragEvent gRecyclerTop = null;
/**
- * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
- * action is ACTION_DRAG_STARTED means that a drag operation has been initiated. The
- * view receiving this DragEvent should inspect the metadata of the dragged content,
- * available via {@link #getClipDescription()}, and return {@code true} from
- * {@link View#onDragEvent(DragEvent)} if the view is prepared to accept a drop of
- * that clip data. If the view chooses to present a visual indication that it is
- * a valid target of the ongoing drag, then it should draw that indication in response
- * to this event.
+ * Action constant returned by {@link #getAction()}: Signals the start of a
+ * drag and drop operation. The View should return {@code true} from its
+ * {@link View#onDragEvent(DragEvent) onDragEvent()} handler method or
+ * {@link View.View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()} listener
+ * if it can accept a drop. The onDragEvent() or onDrag() methods usually inspect the metadata
+ * from {@link #getClipDescription()} to determine if they can accept the data contained in
+ * this drag. For an operation that doesn't represent data transfer, these methods may
+ * perform other actions to determine whether or not the View should accept the drag.
+ * If the View wants to indicate that it is a valid drop target, it can also react by
+ * changing its appearance.
* <p>
- * A view will only receive ACTION_DRAG_ENTERED, ACTION_DRAG_LOCATION, ACTION_DRAG_EXITED,
- * and ACTION_DRAG_LOCATION events if it returns {@code true} in response to the
- * ACTION_DRAG_STARTED event.
+ * A View only receives further drag events if it returns {@code true} in response to
+ * ACTION_DRAG_STARTED.
+ * </p>
+ * @see #ACTION_DRAG_ENDED
*/
public static final int ACTION_DRAG_STARTED = 1;
/**
- * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
- * action is ACTION_DRAG_LOCATION means that the drag operation is currently hovering
- * over the view. The {@link #getX()} and {@link #getY()} methods supply the location
- * of the drag point within the view's coordinate system.
+ * Action constant returned by {@link #getAction()}: Sent to a View after
+ * {@link #ACTION_DRAG_ENTERED} if the drag shadow is still within the View object's bounding
+ * box. The {@link #getX()} and {@link #getY()} methods supply
+ * the X and Y position of of the drag point within the View object's bounding box.
* <p>
- * A view will receive an ACTION_DRAG_ENTERED event before receiving any
- * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an
- * ACTION_DRAG_EXITED event is delivered to the view, after which no more
- * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view,
- * of course).
+ * A View receives an {@link #ACTION_DRAG_ENTERED} event before receiving any
+ * ACTION_DRAG_LOCATION events.
+ * </p>
+ * <p>
+ * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the
+ * drag shadow out of the View object's bounding box. If the user moves the drag shadow back
+ * into the View object's bounding box, the View receives an ACTION_DRAG_ENTERED again before
+ * receiving any more ACTION_DRAG_LOCATION events.
+ * </p>
+ * @see #ACTION_DRAG_ENTERED
+ * @see #getX()
+ * @see #getY()
*/
public static final int ACTION_DRAG_LOCATION = 2;
/**
- * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
- * action is ACTION_DROP means that the dragged content has been dropped on this view.
- * The view should retrieve the content via {@link #getClipData()} and act on it
- * appropriately. The {@link #getX()} and {@link #getY()} methods supply the location
- * of the drop point within the view's coordinate system.
+ * Action constant returned by {@link #getAction()}: Signals to a View that the user
+ * has released the drag shadow, and the drag point is within the bounding box of the View.
+ * The View should retrieve the data from the DragEvent by calling {@link #getClipData()}.
+ * The methods {@link #getX()} and {@link #getY()} return the X and Y position of the drop point
+ * within the View object's bounding box.
* <p>
- * The view should return {@code true} from its {@link View#onDragEvent(DragEvent)}
- * method in response to this event if it accepted the content, and {@code false}
- * if it ignored the drop.
+ * The View should return {@code true} from its {@link View#onDragEvent(DragEvent)}
+ * handler or {@link View.View.OnDragListener#onDrag(View,DragEvent) OnDragListener.onDrag()}
+ * listener if it accepted the drop, and {@code false} if it ignored the drop.
+ * </p>
+ * <p>
+ * The View can also react to this action by changing its appearance.
+ * </p>
+ * @see #getClipData()
+ * @see #getX()
+ * @see #getY()
*/
public static final int ACTION_DROP = 3;
/**
- * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
- * action is ACTION_DRAG_ENDED means that the drag operation has concluded. A view
- * that is drawing a visual indication of drag acceptance should return to its usual
- * drawing state in response to this event.
+ * Action constant returned by {@link #getAction()}: Signals to a View that the drag and drop
+ * operation has concluded. A View that changed its appearance during the operation should
+ * return to its usual drawing state in response to this event.
* <p>
* All views that received an ACTION_DRAG_STARTED event will receive the
- * ACTION_DRAG_ENDED event even if they are not currently visible when the drag
- * ends.
+ * ACTION_DRAG_ENDED event even if they are not currently visible when the drag ends.
+ * </p>
+ * <p>
+ * The View object can call {@link #getResult()} to see the result of the operation.
+ * If a View returned {@code true} in response to {@link #ACTION_DROP}, then
+ * getResult() returns {@code true}, otherwise it returns {@code false}.
+ * </p>
+ * @see #ACTION_DRAG_STARTED
+ * @see #getResult()
*/
public static final int ACTION_DRAG_ENDED = 4;
/**
- * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
- * action is ACTION_DRAG_ENTERED means that the drag point has entered the view's
- * bounds. If the view changed its visual state in response to the ACTION_DRAG_ENTERED
- * event, it should return to its normal drag-in-progress visual state in response to
- * this event.
+ * Action constant returned by {@link #getAction()}: Signals to a View that the drag point has
+ * entered the bounding box of the View.
* <p>
- * A view will receive an ACTION_DRAG_ENTERED event before receiving any
- * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an
- * ACTION_DRAG_EXITED event is delivered to the view, after which no more
- * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view,
- * of course).
+ * If the View can accept a drop, it can react to ACTION_DRAG_ENTERED
+ * by changing its appearance in a way that tells the user that the View is the current
+ * drop target.
+ * </p>
+ * The system stops sending ACTION_DRAG_LOCATION events to a View once the user moves the
+ * drag shadow out of the View object's bounding box. If the user moves the drag shadow back
+ * into the View object's bounding box, the View receives an ACTION_DRAG_ENTERED again before
+ * receiving any more ACTION_DRAG_LOCATION events.
+ * </p>
+ * @see #ACTION_DRAG_ENTERED
+ * @see #ACTION_DRAG_LOCATION
*/
public static final int ACTION_DRAG_ENTERED = 5;
/**
- * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
- * action is ACTION_DRAG_ENTERED means that the drag point has entered the view's
- * bounds. If the view chooses to present a visual indication that it will receive
- * the drop if it occurs now, then it should draw that indication in response to
- * this event.
+ * Action constant returned by {@link #getAction()}: Signals that the user has moved the
+ * drag shadow outside the bounding box of the View.
+ * The View can react by changing its appearance in a way that tells the user that
+ * View is no longer the immediate drop target.
* <p>
- * A view will receive an ACTION_DRAG_ENTERED event before receiving any
- * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an
- * ACTION_DRAG_EXITED event is delivered to the view, after which no more
- * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view,
- * of course).
+ * After the system sends an ACTION_DRAG_EXITED event to the View, the View receives no more
+ * ACTION_DRAG_LOCATION events until the user drags the drag shadow back over the View.
+ * </p>
+ *
*/
-public static final int ACTION_DRAG_EXITED = 6;
+ public static final int ACTION_DRAG_EXITED = 6;
private DragEvent() {
}
@@ -175,64 +292,101 @@
/**
* Inspect the action value of this event.
- * @return One of {@link #ACTION_DRAG_STARTED}, {@link #ACTION_DRAG_ENDED},
- * {@link #ACTION_DROP}, {@link #ACTION_DRAG_ENTERED}, {@link #ACTION_DRAG_EXITED},
- * or {@link #ACTION_DRAG_LOCATION}.
+ * @return One of the following action constants, in the order in which they usually occur
+ * during a drag and drop operation:
+ * <ul>
+ * <li>{@link #ACTION_DRAG_STARTED}</li>
+ * <li>{@link #ACTION_DRAG_ENTERED}</li>
+ * <li>{@link #ACTION_DRAG_LOCATION}</li>
+ * <li>{@link #ACTION_DROP}</li>
+ * <li>{@link #ACTION_DRAG_EXITED}</li>
+ * <li>{@link #ACTION_DRAG_ENDED}</li>
+ * </ul>
*/
public int getAction() {
return mAction;
}
/**
- * For ACTION_DRAG_LOCATION and ACTION_DROP events, returns the x coordinate of the
- * drag point.
- * @return The current drag point's x coordinate, when relevant.
+ * Gets the X coordinate of the drag point. The value is only valid if the event action is
+ * {@link #ACTION_DRAG_LOCATION} or {@link #ACTION_DROP}.
+ * @return The current drag point's Y coordinate
*/
public float getX() {
return mX;
}
/**
- * For ACTION_DRAG_LOCATION and ACTION_DROP events, returns the y coordinate of the
- * drag point.
- * @return The current drag point's y coordinate, when relevant.
+ * Gets the Y coordinate of the drag point. The value is valid if the
+ * event action is {@link #ACTION_DRAG_ENTERED}, {@link #ACTION_DRAG_LOCATION},
+ * {@link #ACTION_DROP}, or {@link #ACTION_DRAG_EXITED}.
+ * @return The current drag point's Y coordinate
*/
public float getY() {
return mY;
}
/**
- * Provides the data payload of the drag operation. This payload is only available
- * for events whose action value is ACTION_DROP.
- * @return The ClipData containing the data being dropped on the view.
+ * Returns the {@link android.content.ClipData} object sent to the system as part of the call
+ * to
+ * {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+ * This method only returns valid data if the event action is {@link #ACTION_DROP}.
+ * @return The ClipData sent to the system by startDrag().
*/
public ClipData getClipData() {
return mClipData;
}
/**
- * Provides a description of the drag operation's data payload. This payload is
- * available for all DragEvents other than ACTION_DROP.
- * @return A ClipDescription describing the contents of the data being dragged.
+ * Returns the {@link android.content.ClipDescription} object contained in the
+ * {@link android.content.ClipData} object sent to the system as part of the call to
+ * {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+ * The drag handler or listener for a View can use the metadata in this object to decide if the
+ * View can accept the dragged View object's data.
+ * <p>
+ * This method returns valid data for all event actions.
+ * @return The ClipDescription that was part of the ClipData sent to the system by startDrag().
*/
public ClipDescription getClipDescription() {
return mClipDescription;
}
/**
- * Provides the local state object passed as the {@code myLocalState} parameter to
- * View.startDrag(). The object will always be null here if the application receiving
- * the DragEvent is not the one that started the drag.
+ * Returns the local state object sent to the system as part of the call to
+ * {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+ * The object is intended to provide local information about the drag and drop operation. For
+ * example, it can indicate whether the drag and drop operation is a copy or a move.
+ * <p>
+ * This method returns valid data for all event actions.
+ * </p>
+ * @return The local state object sent to the system by startDrag().
*/
public Object getLocalState() {
return mLocalState;
}
/**
- * Provides an indication of whether the drag operation concluded successfully.
- * This method is only available on ACTION_DRAG_ENDED events.
- * @return {@code true} if the drag operation ended with an accepted drop; {@code false}
- * otherwise.
+ * <p>
+ * Returns an indication of the result of the drag and drop operation.
+ * This method only returns valid data if the action type is {@link #ACTION_DRAG_ENDED}.
+ * The return value depends on what happens after the user releases the drag shadow.
+ * </p>
+ * <p>
+ * If the user releases the drag shadow on a View that can accept a drop, the system sends an
+ * {@link #ACTION_DROP} event to the View object's drag event listener. If the listener
+ * returns {@code true}, then getResult() will return {@code true}.
+ * If the listener returns {@code false}, then getResult() returns {@code false}.
+ * </p>
+ * <p>
+ * Notice that getResult() also returns {@code false} if no {@link #ACTION_DROP} is sent. This
+ * happens, for example, when the user releases the drag shadow over an area outside of the
+ * application. In this case, the system sends out {@link #ACTION_DRAG_ENDED} for the current
+ * operation, but never sends out {@link #ACTION_DROP}.
+ * </p>
+ * @return {@code true} if a drag event listener returned {@code true} in response to
+ * {@link #ACTION_DROP}. If the system did not send {@link #ACTION_DROP} before
+ * {@link #ACTION_DRAG_ENDED}, or if the listener returned {@code false} in response to
+ * {@link #ACTION_DROP}, then {@code false} is returned.
*/
public boolean getResult() {
return mDragResult;
@@ -271,6 +425,11 @@
}
}
+ /**
+ * Returns a string containing a concise, human-readable representation of this DragEvent
+ * object.
+ * @return A string representation of the DragEvent object.
+ */
@Override
public String toString() {
return "DragEvent{" + Integer.toHexString(System.identityHashCode(this))
@@ -281,10 +440,20 @@
/* Parcelable interface */
+ /**
+ * Returns information about the {@link android.os.Parcel} representation of this DragEvent
+ * object.
+ * @return Information about the {@link android.os.Parcel} representation.
+ */
public int describeContents() {
return 0;
}
+ /**
+ * Creates a {@link android.os.Parcel} object from this DragEvent object.
+ * @param dest A {@link android.os.Parcel} object in which to put the DragEvent object.
+ * @param flags Flags to store in the Parcel.
+ */
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mAction);
dest.writeFloat(mX);
@@ -304,6 +473,9 @@
}
}
+ /**
+ * A container for creating a DragEvent from a Parcel.
+ */
public static final Parcelable.Creator<DragEvent> CREATOR =
new Parcelable.Creator<DragEvent>() {
public DragEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 86e557d..def9668 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -521,7 +521,7 @@
* The framework provides basic support for views that wish to internally
* scroll their content. This includes keeping track of the X and Y scroll
* offset as well as mechanisms for drawing scrollbars. See
- * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
+ * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
* {@link #awakenScrollBars()} for more details.
* </p>
*
@@ -1645,27 +1645,27 @@
* @hide
*/
static final int OPAQUE_MASK = 0x01800000;
-
+
/**
* Indicates a prepressed state;
* the short time between ACTION_DOWN and recognizing
* a 'real' press. Prepressed is used to recognize quick taps
* even when they are shorter than ViewConfiguration.getTapTimeout().
- *
+ *
* @hide
*/
private static final int PREPRESSED = 0x02000000;
-
+
/**
* Indicates whether the view is temporarily detached.
*
* @hide
*/
static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
-
+
/**
* Indicates that we should awaken scroll bars once attached
- *
+ *
* @hide
*/
private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
@@ -1720,14 +1720,14 @@
/**
* View has requested the status bar to be visible (the default).
*
- * @see #setSystemUiVisibility(int)
+ * @see #setSystemUiVisibility(int)
*/
public static final int STATUS_BAR_VISIBLE = 0;
/**
* View has requested the status bar to be visible (the default).
*
- * @see #setSystemUiVisibility(int)
+ * @see #setSystemUiVisibility(int)
*/
public static final int STATUS_BAR_HIDDEN = 0x00000001;
@@ -1950,8 +1950,8 @@
private int mPrevWidth = -1;
private int mPrevHeight = -1;
- private boolean mLastIsOpaque;
-
+ private boolean mLastIsOpaque;
+
/**
* Convenience value to check for float values that are close enough to zero to be considered
* zero.
@@ -2225,7 +2225,7 @@
private CheckForLongPress mPendingCheckForLongPress;
private CheckForTap mPendingCheckForTap = null;
private PerformClick mPerformClick;
-
+
private UnsetPressedState mUnsetPressedState;
/**
@@ -2266,7 +2266,7 @@
* Special tree observer used when mAttachInfo is null.
*/
private ViewTreeObserver mFloatingTreeObserver;
-
+
/**
* Cache the touch slop from the context that created the view.
*/
@@ -2306,11 +2306,11 @@
/**
* Indicates that the view does not have a layer.
- *
- * @see #getLayerType()
- * @see #setLayerType(int, android.graphics.Paint)
+ *
+ * @see #getLayerType()
+ * @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_SOFTWARE
- * @see #LAYER_TYPE_HARDWARE
+ * @see #LAYER_TYPE_HARDWARE
*/
public static final int LAYER_TYPE_NONE = 0;
@@ -2318,7 +2318,7 @@
* <p>Indicates that the view has a software layer. A software layer is backed
* by a bitmap and causes the view to be rendered using Android's software
* rendering pipeline, even if hardware acceleration is enabled.</p>
- *
+ *
* <p>Software layers have various usages:</p>
* <p>When the application is not using hardware acceleration, a software layer
* is useful to apply a specific color filter and/or blending mode and/or
@@ -2334,11 +2334,11 @@
* potentially be slow (particularly when hardware acceleration is turned on
* since the layer will have to be uploaded into a hardware texture after every
* update.)</p>
- *
- * @see #getLayerType()
- * @see #setLayerType(int, android.graphics.Paint)
+ *
+ * @see #getLayerType()
+ * @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_NONE
- * @see #LAYER_TYPE_HARDWARE
+ * @see #LAYER_TYPE_HARDWARE
*/
public static final int LAYER_TYPE_SOFTWARE = 1;
@@ -2349,7 +2349,7 @@
* rendering pipeline, but only if hardware acceleration is turned on for the
* view hierarchy. When hardware acceleration is turned off, hardware layers
* behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
- *
+ *
* <p>A hardware layer is useful to apply a specific color filter and/or
* blending mode and/or translucency to a view and all its children.</p>
* <p>A hardware layer can be used to cache a complex view tree into a
@@ -2359,14 +2359,14 @@
* <p>A hardware layer can also be used to increase the rendering quality when
* rotation transformations are applied on a view. It can also be used to
* prevent potential clipping issues when applying 3D transforms on a view.</p>
- *
- * @see #getLayerType()
+ *
+ * @see #getLayerType()
* @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
*/
public static final int LAYER_TYPE_HARDWARE = 2;
-
+
@ViewDebug.ExportedProperty(category = "drawing", mapping = {
@ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
@ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
@@ -2668,7 +2668,7 @@
break;
case R.styleable.View_onClick:
if (context.isRestricted()) {
- throw new IllegalStateException("The android:onClick attribute cannot "
+ throw new IllegalStateException("The android:onClick attribute cannot "
+ "be used within a restricted context");
}
@@ -2907,19 +2907,19 @@
initScrollCache();
final ScrollabilityCache scrollabilityCache = mScrollCache;
-
+
if (scrollabilityCache.scrollBar == null) {
scrollabilityCache.scrollBar = new ScrollBarDrawable();
}
-
+
final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
if (!fadeScrollbars) {
scrollabilityCache.state = ScrollabilityCache.ON;
}
scrollabilityCache.fadeScrollBars = fadeScrollbars;
-
-
+
+
scrollabilityCache.scrollBarFadeDuration = a.getInt(
R.styleable.View_scrollbarFadeDuration, ViewConfiguration
.getScrollBarFadeDuration());
@@ -2927,7 +2927,7 @@
R.styleable.View_scrollbarDefaultDelayBeforeFade,
ViewConfiguration.getScrollDefaultDelay());
-
+
scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
com.android.internal.R.styleable.View_scrollbarSize,
ViewConfiguration.get(mContext).getScaledScrollBarSize());
@@ -3163,8 +3163,11 @@
}
/**
- * Register a callback to be invoked when a drag event is sent to this view.
- * @param l The drag listener to attach to this view
+ * Register a drag event listener callback object for this View. The parameter is
+ * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
+ * View, the system calls the
+ * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
+ * @param l An implementation of {@link android.view.View.OnDragListener}.
*/
public void setOnDragListener(OnDragListener l) {
mOnDragListener = l;
@@ -3375,7 +3378,7 @@
if (mOnFocusChangeListener != null) {
mOnFocusChangeListener.onFocusChange(this, gainFocus);
}
-
+
if (mAttachInfo != null) {
mAttachInfo.mKeyDispatchState.reset(this);
}
@@ -4523,7 +4526,7 @@
public KeyEvent.DispatcherState getKeyDispatcherState() {
return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
}
-
+
/**
* Dispatch a key event before it is processed by any input method
* associated with the view hierarchy. This can be used to intercept
@@ -4601,7 +4604,7 @@
*
* @param event The motion event to be filtered.
* @return True if the event should be dispatched, false if the event should be dropped.
- *
+ *
* @see #getFilterTouchesWhenObscured
*/
public boolean onFilterTouchEventForSecurity(MotionEvent event) {
@@ -4708,7 +4711,7 @@
* a View moves out of the screen, it might receives a display hint indicating
* the view is not displayed. Applications should not <em>rely</em> on this hint
* as there is no guarantee that they will receive one.
- *
+ *
* @param hint A hint about whether or not this view is displayed:
* {@link #VISIBLE} or {@link #INVISIBLE}.
*/
@@ -4721,7 +4724,7 @@
* a View moves out of the screen, it might receives a display hint indicating
* the view is not displayed. Applications should not <em>rely</em> on this hint
* as there is no guarantee that they will receive one.
- *
+ *
* @param hint A hint about whether or not this view is displayed:
* {@link #VISIBLE} or {@link #INVISIBLE}.
*/
@@ -5174,7 +5177,7 @@
mPrivateFlags |= PRESSED;
refreshDrawableState();
}
-
+
if (!mHasPerformedLongPress) {
// This is a tap, so remove the longpress check
removeLongPressCallback();
@@ -5677,7 +5680,7 @@
/**
* Returns true if the transform matrix is the identity matrix.
* Recomputes the matrix if necessary.
- *
+ *
* @return True if the transform matrix is the identity matrix, false otherwise.
*/
final boolean hasIdentityMatrix() {
@@ -6018,16 +6021,16 @@
/**
* <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
* completely transparent and 1 means the view is completely opaque.</p>
- *
+ *
* <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
* responsible for applying the opacity itself. Otherwise, calling this method is
* equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
- * setting a hardware layer.</p>
+ * setting a hardware layer.</p>
*
* @param alpha The opacity of the view.
*
- * @see #setLayerType(int, android.graphics.Paint)
- *
+ * @see #setLayerType(int, android.graphics.Paint)
+ *
* @attr ref android.R.styleable#View_alpha
*/
public void setAlpha(float alpha) {
@@ -6293,7 +6296,7 @@
/**
* The visual x position of this view, in pixels. This is equivalent to the
* {@link #setTranslationX(float) translationX} property plus the current
- * {@link #getLeft() left} property.
+ * {@link #getLeft() left} property.
*
* @return The visual x position of this view, in pixels.
*/
@@ -6690,7 +6693,7 @@
* provides animated scrolling, the start delay should equal the duration of
* the scrolling animation.
* </p>
- *
+ *
* <p>
* The animation starts only if at least one of the scrollbars is enabled,
* as specified by {@link #isHorizontalScrollBarEnabled()} and
@@ -6699,17 +6702,17 @@
* started, this method calls {@link #invalidate()}; in that case the caller
* should not call {@link #invalidate()}.
* </p>
- *
+ *
* <p>
* This method should be invoked everytime a subclass directly updates the
* scroll parameters.
* </p>
- *
+ *
* @param startDelay the delay, in milliseconds, after which the animation
* should start; when the delay is 0, the animation starts
* immediately
* @return true if the animation is played, false otherwise
- *
+ *
* @see #scrollBy(int, int)
* @see #scrollTo(int, int)
* @see #isHorizontalScrollBarEnabled()
@@ -6720,7 +6723,7 @@
protected boolean awakenScrollBars(int startDelay) {
return awakenScrollBars(startDelay, true);
}
-
+
/**
* <p>
* Trigger the scrollbars to draw. When invoked this method starts an
@@ -6728,30 +6731,30 @@
* provides animated scrolling, the start delay should equal the duration of
* the scrolling animation.
* </p>
- *
+ *
* <p>
* The animation starts only if at least one of the scrollbars is enabled,
* as specified by {@link #isHorizontalScrollBarEnabled()} and
* {@link #isVerticalScrollBarEnabled()}. When the animation is started,
* this method returns true, and false otherwise. If the animation is
- * started, this method calls {@link #invalidate()} if the invalidate parameter
+ * started, this method calls {@link #invalidate()} if the invalidate parameter
* is set to true; in that case the caller
* should not call {@link #invalidate()}.
* </p>
- *
+ *
* <p>
* This method should be invoked everytime a subclass directly updates the
* scroll parameters.
* </p>
- *
+ *
* @param startDelay the delay, in milliseconds, after which the animation
* should start; when the delay is 0, the animation starts
* immediately
- *
+ *
* @param invalidate Wheter this method should call invalidate
- *
+ *
* @return true if the animation is played, false otherwise
- *
+ *
* @see #scrollBy(int, int)
* @see #scrollTo(int, int)
* @see #isHorizontalScrollBarEnabled()
@@ -6761,7 +6764,7 @@
*/
protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
final ScrollabilityCache scrollCache = mScrollCache;
-
+
if (scrollCache == null || !scrollCache.fadeScrollBars) {
return false;
}
@@ -6894,7 +6897,7 @@
public void invalidate() {
invalidate(true);
}
-
+
/**
* This is where the invalidate() work actually happens. A full invalidate()
* causes the drawing cache to be invalidated, but this function can be called with
@@ -6956,7 +6959,7 @@
((View) mParent).mPrivateFlags |= INVALIDATED;
}
}
-
+
/**
* Used to indicate that the parent of this view should be invalidated. This functionality
* is used to force the parent to rebuild its display list (when hardware-accelerated),
@@ -7385,12 +7388,12 @@
protected void recomputePadding() {
setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
}
-
+
/**
* Define whether scrollbars will fade when the view is not scrolling.
- *
+ *
* @param fadeScrollbars wheter to enable fading
- *
+ *
*/
public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
initScrollCache();
@@ -7402,17 +7405,17 @@
scrollabilityCache.state = ScrollabilityCache.ON;
}
}
-
+
/**
- *
+ *
* Returns true if scrollbars will fade when this view is not scrolling
- *
+ *
* @return true if scrollbar fading is enabled
*/
public boolean isScrollbarFadingEnabled() {
- return mScrollCache != null && mScrollCache.fadeScrollBars;
+ return mScrollCache != null && mScrollCache.fadeScrollBars;
}
-
+
/**
* <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
* inset. When inset, they add to the padding of the view. And the scrollbars
@@ -7579,30 +7582,30 @@
* scrollbars are painted only if they have been awakened first.</p>
*
* @param canvas the canvas on which to draw the scrollbars
- *
+ *
* @see #awakenScrollBars(int)
*/
protected final void onDrawScrollBars(Canvas canvas) {
// scrollbars are drawn only when the animation is running
final ScrollabilityCache cache = mScrollCache;
if (cache != null) {
-
+
int state = cache.state;
-
+
if (state == ScrollabilityCache.OFF) {
return;
}
-
+
boolean invalidate = false;
-
+
if (state == ScrollabilityCache.FADING) {
// We're fading -- get our fade interpolation
if (cache.interpolatorValues == null) {
cache.interpolatorValues = new float[1];
}
-
+
float[] values = cache.interpolatorValues;
-
+
// Stops the animation if we're done
if (cache.scrollBarInterpolator.timeToValues(values) ==
Interpolator.Result.FREEZE_END) {
@@ -7610,8 +7613,8 @@
} else {
cache.scrollBar.setAlpha(Math.round(values[0]));
}
-
- // This will make the scroll bars inval themselves after
+
+ // This will make the scroll bars inval themselves after
// drawing. We only want this when we're fading so that
// we prevent excessive redraws
invalidate = true;
@@ -7621,7 +7624,7 @@
cache.scrollBar.setAlpha(255);
}
-
+
final int viewFlags = mViewFlags;
final boolean drawHorizontalScrollBar =
@@ -7641,7 +7644,7 @@
final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
int left, top, right, bottom;
-
+
if (drawHorizontalScrollBar) {
int size = scrollBar.getSize(false);
if (size <= 0) {
@@ -7653,7 +7656,7 @@
computeHorizontalScrollExtent(), false);
final int verticalScrollBarGap = drawVerticalScrollBar ?
getVerticalScrollbarWidth() : 0;
- top = scrollY + height - size - (mUserPaddingBottom & inside);
+ top = scrollY + height - size - (mUserPaddingBottom & inside);
left = scrollX + (mPaddingLeft & inside);
right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
bottom = top + size;
@@ -8038,8 +8041,8 @@
if (state != BaseSavedState.EMPTY_STATE && state != null) {
throw new IllegalArgumentException("Wrong state class, expecting View State but "
+ "received " + state.getClass().toString() + " instead. This usually happens "
- + "when two views of different type have the same id in the same hierarchy. "
- + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
+ + "when two views of different type have the same id in the same hierarchy. "
+ + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
+ "other views do not use the same id.");
}
}
@@ -8064,7 +8067,7 @@
*
* <p>Note: if this view's parent addStateFromChildren property is enabled and this
* property is enabled, an exception will be thrown.</p>
- *
+ *
* <p>Note: if the child view uses and updates additionnal states which are unknown to the
* parent, these states should not be affected by this method.</p>
*
@@ -8095,7 +8098,7 @@
* <p>Specifies the type of layer backing this view. The layer can be
* {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
* {@link #LAYER_TYPE_HARDWARE hardware}.</p>
- *
+ *
* <p>A layer is associated with an optional {@link android.graphics.Paint}
* instance that controls how the layer is composed on screen. The following
* properties of the paint are taken into account when composing the layer:</p>
@@ -8104,35 +8107,35 @@
* <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
* <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
* </ul>
- *
+ *
* <p>If this view has an alpha value set to < 1.0 by calling
* {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
* this view's alpha value. Calling {@link #setAlpha(float)} is therefore
* equivalent to setting a hardware layer on this view and providing a paint with
* the desired alpha value.<p>
- *
+ *
* <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
* {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
* for more information on when and how to use layers.</p>
- *
+ *
* @param layerType The ype of layer to use with this view, must be one of
* {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
* {@link #LAYER_TYPE_HARDWARE}
* @param paint The paint used to compose the layer. This argument is optional
* and can be null. It is ignored when the layer type is
* {@link #LAYER_TYPE_NONE}
- *
- * @see #getLayerType()
+ *
+ * @see #getLayerType()
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
* @see #LAYER_TYPE_HARDWARE
- * @see #setAlpha(float)
- *
+ * @see #setAlpha(float)
+ *
* @attr ref android.R.styleable#View_layerType
*/
public void setLayerType(int layerType, Paint paint) {
if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
- throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
+ throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
+ "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
}
@@ -8152,7 +8155,7 @@
mDrawingCache.recycle();
mDrawingCache = null;
}
-
+
if (mUnscaledDrawingCache != null) {
mUnscaledDrawingCache.recycle();
mUnscaledDrawingCache = null;
@@ -8180,11 +8183,11 @@
* a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
* Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
* for more information on the different types of layers.
- *
+ *
* @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
* {@link #LAYER_TYPE_HARDWARE}
- *
- * @see #setLayerType(int, android.graphics.Paint)
+ *
+ * @see #setLayerType(int, android.graphics.Paint)
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
* @see #LAYER_TYPE_HARDWARE
@@ -8192,7 +8195,7 @@
public int getLayerType() {
return mLayerType;
}
-
+
/**
* <p>Returns a hardware layer that can be used to draw this view again
* without executing its draw method.</p>
@@ -8206,7 +8209,7 @@
final int width = mRight - mLeft;
final int height = mBottom - mTop;
-
+
if (width == 0 || height == 0) {
return null;
}
@@ -8233,7 +8236,7 @@
canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-
+
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
mPrivateFlags &= ~DIRTY_MASK;
@@ -8241,7 +8244,7 @@
} else {
draw(canvas);
}
-
+
canvas.restoreToCount(restoreCount);
} finally {
canvas.onPostDraw();
@@ -8260,7 +8263,7 @@
* the cache is enabled. To benefit from the cache, you must request the drawing cache by
* calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
* null.</p>
- *
+ *
* <p>Enabling the drawing cache is similar to
* {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
* acceleration is turned off. When hardware acceleration is turned on, enabling the
@@ -8278,7 +8281,7 @@
* @see #isDrawingCacheEnabled()
* @see #getDrawingCache()
* @see #buildDrawingCache()
- * @see #setLayerType(int, android.graphics.Paint)
+ * @see #setLayerType(int, android.graphics.Paint)
*/
public void setDrawingCacheEnabled(boolean enabled) {
setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
@@ -8300,7 +8303,7 @@
/**
* Debugging utility which recursively outputs the dirty state of a view and its
* descendants.
- *
+ *
* @hide
*/
public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
@@ -8345,11 +8348,11 @@
}
return true;
}
-
+
/**
* <p>Returns a display list that can be used to draw this view again
* without executing its draw method.</p>
- *
+ *
* @return A DisplayList ready to replay, or null if caching is not enabled.
*
* @hide
@@ -8398,7 +8401,7 @@
computeScroll();
canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-
+
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
mPrivateFlags &= ~DIRTY_MASK;
@@ -8406,7 +8409,7 @@
} else {
draw(canvas);
}
-
+
canvas.restoreToCount(restoreCount);
} finally {
canvas.onPostDraw();
@@ -8423,9 +8426,9 @@
/**
* <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
- *
+ *
* @return A non-scaled bitmap representing this view or null if cache is disabled.
- *
+ *
* @see #getDrawingCache(boolean)
*/
public Bitmap getDrawingCache() {
@@ -8439,7 +8442,7 @@
* draw from the cache when the cache is enabled. To benefit from the cache, you must
* request the drawing cache by calling this method and draw it on screen if the
* returned bitmap is not null.</p>
- *
+ *
* <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
* this method will create a bitmap of the same size as this view. Because this bitmap
* will be drawn scaled by the parent ViewGroup, the result on screen might show
@@ -8447,13 +8450,13 @@
* the auto scaling to true. Doing so, however, will generate a bitmap of a different
* size than the view. This implies that your application must be able to handle this
* size.</p>
- *
+ *
* @param autoScale Indicates whether the generated bitmap should be scaled based on
* the current density of the screen when the application is in compatibility
* mode.
*
* @return A bitmap representing this view or null if cache is disabled.
- *
+ *
* @see #setDrawingCacheEnabled(boolean)
* @see #isDrawingCacheEnabled()
* @see #buildDrawingCache(boolean)
@@ -8519,7 +8522,7 @@
/**
* <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
- *
+ *
* @see #buildDrawingCache(boolean)
*/
public void buildDrawingCache() {
@@ -8532,7 +8535,7 @@
* <p>If you call {@link #buildDrawingCache()} manually without calling
* {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
* should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
- *
+ *
* <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
* this method will create a bitmap of the same size as this view. Because this bitmap
* will be drawn scaled by the parent ViewGroup, the result on screen might show
@@ -8540,10 +8543,10 @@
* the auto scaling to true. Doing so, however, will generate a bitmap of a different
* size than the view. This implies that your application must be able to handle this
* size.</p>
- *
+ *
* <p>You should avoid calling this method when hardware acceleration is enabled. If
* you do not need the drawing cache bitmap, calling this method will increase memory
- * usage and cause the view to be rendered in software once, thus negatively impacting
+ * usage and cause the view to be rendered in software once, thus negatively impacting
* performance.</p>
*
* @see #getDrawingCache()
@@ -8656,12 +8659,12 @@
computeScroll();
final int restoreCount = canvas.save();
-
+
if (autoScale && scalingRequired) {
final float scale = attachInfo.mApplicationScale;
canvas.scale(scale, scale);
}
-
+
canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= DRAWN;
@@ -8702,14 +8705,14 @@
final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
width = (int) ((width * scale) + 0.5f);
height = (int) ((height * scale) + 0.5f);
-
+
Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
if (bitmap == null) {
throw new OutOfMemoryError();
}
bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
-
+
Canvas canvas;
if (attachInfo != null) {
canvas = attachInfo.mCanvas;
@@ -8859,7 +8862,7 @@
/**
* <p>Indicates whether this view is attached to an hardware accelerated
* window or not.</p>
- *
+ *
* <p>Even if this method returns true, it does not mean that every call
* to {@link #draw(android.graphics.Canvas)} will be made with an hardware
* accelerated {@link android.graphics.Canvas}. For instance, if this view
@@ -8867,14 +8870,14 @@
* window is hardware accelerated,
* {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
* return false, and this method will return true.</p>
- *
+ *
* @return True if the view is attached to a window and the window is
* hardware accelerated; false in any other case.
*/
public boolean isHardwareAccelerated() {
return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
}
-
+
/**
* Manually render this view (and all of its children) to the given Canvas.
* The view must have already done a full layout before this function is
@@ -10941,21 +10944,35 @@
}
/**
- * !!! TODO: real docs
- *
- * The base class implementation makes the shadow the same size and appearance
- * as the view itself, and positions it with its center at the touch point.
+ * Creates an image that the system displays during the drag and drop
+ * operation. This is called a "drag shadow". The default implementation
+ * for a DragShadowBuilder based on a View returns an image that has exactly the same
+ * appearance as the given View. The default also positions the center of the drag shadow
+ * directly under the touch point. If no View is provided (the constructor with no parameters
+ * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
+ * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
+ * default is an invisible drag shadow.
+ * <p>
+ * You are not required to use the View you provide to the constructor as the basis of the
+ * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
+ * anything you want as the drag shadow.
+ * </p>
+ * <p>
+ * You pass a DragShadowBuilder object to the system when you start the drag. The system
+ * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
+ * size and position of the drag shadow. It uses this data to construct a
+ * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
+ * so that your application can draw the shadow image in the Canvas.
+ * </p>
*/
public static class DragShadowBuilder {
private final WeakReference<View> mView;
/**
- * Construct a shadow builder object for use with the given View object. The
- * default implementation will construct a drag shadow the same size and
- * appearance as the supplied View.
- *
- * @param view A view within the application's layout whose appearance
- * should be replicated as the drag shadow.
+ * Constructs a shadow image builder based on a View. By default, the resulting drag
+ * shadow will have the same appearance and dimensions as the View, with the touch point
+ * over the center of the View.
+ * @param view A View. Any View in scope can be used.
*/
public DragShadowBuilder(View view) {
mView = new WeakReference<View>(view);
@@ -10966,7 +10983,8 @@
* constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
* and {@link #onDrawShadow(Canvas)} methods are also overridden in order
* to supply the drag shadow's dimensions and appearance without
- * reference to any View object.
+ * reference to any View object. If they are not overridden, then the result is an
+ * invisible drag shadow.
*/
public DragShadowBuilder() {
mView = new WeakReference<View>(null);
@@ -10987,22 +11005,24 @@
}
/**
- * Provide the draggable-shadow metrics for the operation: the dimensions of
- * the shadow image itself, and the point within that shadow that should
+ * Provides the metrics for the shadow image. These include the dimensions of
+ * the shadow image, and the point within that shadow that should
* be centered under the touch location while dragging.
* <p>
* The default implementation sets the dimensions of the shadow to be the
- * same as the dimensions of the View object that had been supplied to the
- * {@link #View.DragShadowBuilder(View)} constructor
- * when the builder object was instantiated, and centers the shadow under the touch
- * point.
+ * same as the dimensions of the View itself and centers the shadow under
+ * the touch point.
+ * </p>
*
- * @param shadowSize The application should set the {@code x} member of this
- * parameter to the desired shadow width, and the {@code y} member to
- * the desired height.
- * @param shadowTouchPoint The application should set this point to be the
- * location within the shadow that should track directly underneath
- * the touch point on the screen during a drag.
+ * @param shadowSize A {@link android.graphics.Point} containing the width and height
+ * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
+ * desired width and must set {@link android.graphics.Point#y} to the desired height of the
+ * image.
+ *
+ * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
+ * shadow image that should be underneath the touch point during the drag and drop
+ * operation. Your application must set {@link android.graphics.Point#x} to the
+ * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
*/
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
final View view = mView.get();
@@ -11015,16 +11035,11 @@
}
/**
- * Draw the shadow image for the upcoming drag. The shadow canvas was
- * created with the dimensions supplied by the
+ * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
+ * based on the dimensions it received from the
* {@link #onProvideShadowMetrics(Point, Point)} callback.
- * <p>
- * The default implementation replicates the appearance of the View object
- * that had been supplied to the
- * {@link #View.DragShadowBuilder(View)}
- * constructor when the builder object was instantiated.
*
- * @param canvas
+ * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
*/
public void onDrawShadow(Canvas canvas) {
final View view = mView.get();
@@ -11037,24 +11052,43 @@
}
/**
- * Drag and drop. App calls startDrag(), then callbacks to the shadow builder's
- * {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} and
- * {@link DragShadowBuilder#onDrawShadow(Canvas)} methods happen, then the drag
- * operation is handed over to the OS.
- * !!! TODO: real docs
- *
- * @param data !!! TODO
- * @param shadowBuilder !!! TODO
- * @param myLocalState An arbitrary object that will be passed as part of every DragEvent
- * delivered to the calling application during the course of the current drag operation.
- * This object is private to the application that called startDrag(), and is not
- * visible to other applications. It provides a lightweight way for the application to
- * propagate information from the initiator to the recipient of a drag within its own
- * application; for example, to help disambiguate between 'copy' and 'move' semantics.
- * @param flags Flags affecting the drag operation. At present no flags are defined;
- * pass 0 for this parameter.
- * @return {@code true} if the drag operation was initiated successfully; {@code false} if
- * an error prevented the drag from taking place.
+ * Starts a drag and drop operation. When your application calls this method, it passes a
+ * {@link android.view.View.DragShadowBuilder} object to the system. The
+ * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
+ * to get metrics for the drag shadow, and then calls the object's
+ * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
+ * <p>
+ * Once the system has the drag shadow, it begins the drag and drop operation by sending
+ * drag events to all the View objects in your application that are currently visible. It does
+ * this either by calling the View object's drag listener (an implementation of
+ * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
+ * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
+ * Both are passed a {@link android.view.DragEvent} object that has a
+ * {@link android.view.DragEvent#getAction()} value of
+ * {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
+ * </p>
+ * <p>
+ * Your application can invoke startDrag() on any attached View object. The View object does not
+ * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
+ * be related to the View the user selected for dragging.
+ * </p>
+ * @param data A {@link android.content.ClipData} object pointing to the data to be
+ * transferred by the drag and drop operation.
+ * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
+ * drag shadow.
+ * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
+ * drop operation. This Object is put into every DragEvent object sent by the system during the
+ * current drag.
+ * <p>
+ * myLocalState is a lightweight mechanism for the sending information from the dragged View
+ * to the target Views. For example, it can contain flags that differentiate between a
+ * a copy operation and a move operation.
+ * </p>
+ * @param flags Flags that control the drag and drop operation. No flags are currently defined,
+ * so the parameter should be set to 0.
+ * @return {@code true} if the method completes successfully, or
+ * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
+ * do a drag, and so no drag operation is in progress.
*/
public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
Object myLocalState, int flags) {
@@ -11113,42 +11147,48 @@
}
/**
- * Drag-and-drop event dispatch. The event.getAction() verb is one of the DragEvent
- * constants DRAG_STARTED_EVENT, DRAG_EVENT, DROP_EVENT, and DRAG_ENDED_EVENT.
- *
- * For DRAG_STARTED_EVENT, event.getClipDescription() describes the content
- * being dragged. onDragEvent() should return 'true' if the view can handle
- * a drop of that content. A view that returns 'false' here will receive no
- * further calls to onDragEvent() about the drag/drop operation.
- *
- * For DRAG_ENTERED, event.getClipDescription() describes the content being
- * dragged. This will be the same content description passed in the
- * DRAG_STARTED_EVENT invocation.
- *
- * For DRAG_EXITED, event.getClipDescription() describes the content being
- * dragged. This will be the same content description passed in the
- * DRAG_STARTED_EVENT invocation. The view should return to its approriate
- * drag-acceptance visual state.
- *
- * For DRAG_LOCATION_EVENT, event.getX() and event.getY() give the location in View
- * coordinates of the current drag point. The view must return 'true' if it
- * can accept a drop of the current drag content, false otherwise.
- *
- * For DROP_EVENT, event.getX() and event.getY() give the location of the drop
- * within the view; also, event.getClipData() returns the full data payload
- * being dropped. The view should return 'true' if it consumed the dropped
- * content, 'false' if it did not.
- *
- * For DRAG_ENDED_EVENT, the 'event' argument may be null. The view should return
- * to its normal visual state.
+ * Handles drag events sent by the system following a call to
+ * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
+ *<p>
+ * When the system calls this method, it passes a
+ * {@link android.view.DragEvent} object. A call to
+ * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
+ * in DragEvent. The method uses these to determine what is happening in the drag and drop
+ * operation.
+ * @param event The {@link android.view.DragEvent} sent by the system.
+ * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
+ * in DragEvent, indicating the type of drag event represented by this object.
+ * @return {@code true} if the method was successful, otherwise {@code false}.
+ * <p>
+ * The method should return {@code true} in response to an action type of
+ * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
+ * operation.
+ * </p>
+ * <p>
+ * The method should also return {@code true} in response to an action type of
+ * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
+ * {@code false} if it didn't.
+ * </p>
*/
public boolean onDragEvent(DragEvent event) {
return false;
}
/**
- * Views typically don't need to override dispatchDragEvent(); it just calls
- * onDragEvent(event) and passes the result up appropriately.
+ * Detects if this View is enabled and has a drag event listener.
+ * If both are true, then it calls the drag event listener with the
+ * {@link android.view.DragEvent} it received. If the drag event listener returns
+ * {@code true}, then dispatchDragEvent() returns {@code true}.
+ * <p>
+ * For all other cases, the method calls the
+ * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
+ * method and returns its result.
+ * </p>
+ * <p>
+ * This ensures that a drag event is always consumed, even if the View does not have a drag
+ * event listener. However, if the View has a listener and the listener returns true, then
+ * onDragEvent() is not called.
+ * </p>
*/
public boolean dispatchDragEvent(DragEvent event) {
if (mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
@@ -11165,7 +11205,7 @@
*/
public void onCloseSystemDialogs(String reason) {
}
-
+
/**
* Given a Drawable whose bounds have been set to draw into this view,
* update a Region being computed for {@link #gatherTransparentRegion} so
@@ -11497,7 +11537,7 @@
mOriginalWindowAttachCount = mWindowAttachCount;
}
}
-
+
private final class CheckForTap implements Runnable {
public void run() {
mPrivateFlags &= ~PREPRESSED;
@@ -11519,7 +11559,7 @@
public void hackTurnOffWindowResizeAnim(boolean off) {
mAttachInfo.mTurnOffWindowResizeAnim = off;
}
-
+
/**
* Interface definition for a callback to be invoked when a key event is
* dispatched to this view. The callback will be invoked before the key
@@ -11582,11 +11622,11 @@
* Called when a drag event is dispatched to a view. This allows listeners
* to get a chance to override base View behavior.
*
- * @param v The view the drag has been dispatched to.
- * @param event The DragEvent object containing full information
- * about the event.
- * @return true if the listener consumed the DragEvent, false in order to fall
- * back to the view's default handling.
+ * @param v The View that received the drag event.
+ * @param event The {@link android.view.DragEvent} object for the drag event.
+ * @return {@code true} if the drag event was handled successfully, or {@code false}
+ * if the drag event was not handled. Note that {@code false} will trigger the View
+ * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
*/
boolean onDrag(View v, DragEvent event);
}
@@ -11774,7 +11814,7 @@
boolean mHardwareAccelerated;
boolean mHardwareAccelerationRequested;
HardwareRenderer mHardwareRenderer;
-
+
/**
* Scale factor used by the compatibility mode
*/
@@ -11789,7 +11829,7 @@
* If set, ViewRoot doesn't use its lame animation for when the window resizes.
*/
boolean mTurnOffWindowResizeAnim;
-
+
/**
* Left position of this view's window
*/
@@ -11982,7 +12022,7 @@
* instances of View.</p>
*/
private static class ScrollabilityCache implements Runnable {
-
+
/**
* Scrollbars are not visible
*/
@@ -11999,7 +12039,7 @@
public static final int FADING = 2;
public boolean fadeScrollBars;
-
+
public int fadingEdgeLength;
public int scrollBarDefaultDelayBeforeFade;
public int scrollBarFadeDuration;
@@ -12017,7 +12057,7 @@
private static final float[] OPAQUE = { 255 };
private static final float[] TRANSPARENT = { 0.0f };
-
+
/**
* When fading should start. This time moves into the future every time
* a new scroll happens. Measured based on SystemClock.uptimeMillis()
@@ -12062,7 +12102,7 @@
paint.setXfermode(null);
}
}
-
+
public void run() {
long now = AnimationUtils.currentAnimationTimeMillis();
if (now >= fadeStartTime) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 38ac37d..70f90d3 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -50,6 +50,6 @@
initialIntents[i] = (Intent)pa[i];
}
}
- super.onCreate(savedInstanceState, target, title, initialIntents, false);
+ super.onCreate(savedInstanceState, target, title, initialIntents, null, false);
}
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 215e9ae..841de06 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -63,11 +63,12 @@
protected void onCreate(Bundle savedInstanceState) {
onCreate(savedInstanceState, new Intent(getIntent()),
getResources().getText(com.android.internal.R.string.whichApplication),
- null, true);
+ null, null, true);
}
protected void onCreate(Bundle savedInstanceState, Intent intent,
- CharSequence title, Intent[] initialIntents, boolean alwaysUseOption) {
+ CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList,
+ boolean alwaysUseOption) {
super.onCreate(savedInstanceState);
mPm = getPackageManager();
intent.setComponent(null);
@@ -88,7 +89,7 @@
com.android.internal.R.id.clearDefaultHint);
mClearDefaultHint.setVisibility(View.GONE);
}
- mAdapter = new ResolveListAdapter(this, intent, initialIntents);
+ mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList);
if (mAdapter.getCount() > 1) {
ap.mAdapter = mAdapter;
} else if (mAdapter.getCount() == 1) {
@@ -215,14 +216,16 @@
private List<DisplayResolveInfo> mList;
public ResolveListAdapter(Context context, Intent intent,
- Intent[] initialIntents) {
+ Intent[] initialIntents, List<ResolveInfo> rList) {
mIntent = new Intent(intent);
mIntent.setComponent(null);
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- List<ResolveInfo> rList = mPm.queryIntentActivities(
- intent, PackageManager.MATCH_DEFAULT_ONLY
- | (mAlwaysCheck != null ? PackageManager.GET_RESOLVED_FILTER : 0));
+ if (rList == null) {
+ rList = mPm.queryIntentActivities(
+ intent, PackageManager.MATCH_DEFAULT_ONLY
+ | (mAlwaysCheck != null ? PackageManager.GET_RESOLVED_FILTER : 0));
+ }
int N;
if ((rList != null) && ((N = rList.size()) > 0)) {
// Only display the first matches that are either of equal
diff --git a/core/java/com/android/internal/nfc/LlcpSocket.java b/core/java/com/android/internal/nfc/LlcpSocket.java
index 73c09259..63888ae 100644
--- a/core/java/com/android/internal/nfc/LlcpSocket.java
+++ b/core/java/com/android/internal/nfc/LlcpSocket.java
@@ -193,7 +193,7 @@
throw new IOException();
}
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in send(): ", e);
+ Log.e(TAG, "RemoteException in receive(): ", e);
}
return receivedLength;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b682947..b3b80f6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4087,7 +4087,7 @@
// we have gone through a significant charge (from a very low
// level to a now very high level).
if (oldStatus == BatteryManager.BATTERY_STATUS_FULL
- || level >= 95
+ || level >= 90
|| (mDischargeCurrentLevel < 20 && level >= 80)) {
doWrite = true;
resetAllStatsLocked();
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 5fcd0c2..7f23ed5 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -33,5 +33,6 @@
void setLightsOn(boolean on);
void setMenuKeyVisible(boolean visible);
void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
+ void setHardKeyboardStatus(boolean available, boolean enabled);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index c62aeb0..d6ca426 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -45,4 +45,5 @@
void onClearAllNotifications();
void onNotificationClear(String pkg, String tag, int id);
void setSystemUiVisibility(int vis);
+ void setHardKeyboardEnabled(boolean enabled);
}
diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java
index bc749d8..0885b6e 100644
--- a/core/java/com/android/internal/widget/DigitalClock.java
+++ b/core/java/com/android/internal/widget/DigitalClock.java
@@ -34,6 +34,7 @@
import android.widget.RelativeLayout;
import android.widget.TextView;
+import java.lang.ref.WeakReference;
import java.text.DateFormatSymbols;
import java.util.Calendar;
@@ -54,26 +55,45 @@
private TextView mTimeDisplayForeground;
private AmPm mAmPm;
private ContentObserver mFormatChangeObserver;
- private boolean mLive = true;
- private boolean mAttached;
+ private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced
/* called by system on minute ticks */
private final Handler mHandler = new Handler();
- private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (mLive && intent.getAction().equals(
- Intent.ACTION_TIMEZONE_CHANGED)) {
- mCalendar = Calendar.getInstance();
- }
- // Post a runnable to avoid blocking the broadcast.
- mHandler.post(new Runnable() {
- public void run() {
- updateTime();
+ private BroadcastReceiver mIntentReceiver;
+
+ private static class TimeChangedReceiver extends BroadcastReceiver {
+ private WeakReference<DigitalClock> mClock;
+ private Context mContext;
+
+ public TimeChangedReceiver(DigitalClock clock) {
+ mClock = new WeakReference<DigitalClock>(clock);
+ mContext = clock.getContext();
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Post a runnable to avoid blocking the broadcast.
+ final boolean timezoneChanged =
+ intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED);
+ final DigitalClock clock = mClock.get();
+ if (clock != null) {
+ clock.mHandler.post(new Runnable() {
+ public void run() {
+ if (timezoneChanged) {
+ clock.mCalendar = Calendar.getInstance();
}
+ clock.updateTime();
+ }
});
+ } else {
+ try {
+ mContext.unregisterReceiver(this);
+ } catch (RuntimeException e) {
+ // Shouldn't happen
+ }
}
- };
+ }
+ };
static class AmPm {
private TextView mAmPm;
@@ -99,14 +119,27 @@
}
}
- private class FormatChangeObserver extends ContentObserver {
- public FormatChangeObserver() {
+ private static class FormatChangeObserver extends ContentObserver {
+ private WeakReference<DigitalClock> mClock;
+ private Context mContext;
+ public FormatChangeObserver(DigitalClock clock) {
super(new Handler());
+ mClock = new WeakReference<DigitalClock>(clock);
+ mContext = clock.getContext();
}
@Override
public void onChange(boolean selfChange) {
- setDateFormat();
- updateTime();
+ DigitalClock digitalClock = mClock.get();
+ if (digitalClock != null) {
+ digitalClock.setDateFormat();
+ digitalClock.updateTime();
+ } else {
+ try {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ } catch (RuntimeException e) {
+ // Shouldn't happen
+ }
+ }
}
}
@@ -139,11 +172,11 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- if (mAttached) return;
- mAttached = true;
+ mAttached++;
- if (mLive) {
- /* monitor time ticks, time changed, timezone */
+ /* monitor time ticks, time changed, timezone */
+ if (mIntentReceiver == null) {
+ mIntentReceiver = new TimeChangedReceiver(this);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
@@ -152,9 +185,11 @@
}
/* monitor 12/24-hour display preference */
- mFormatChangeObserver = new FormatChangeObserver();
- mContext.getContentResolver().registerContentObserver(
- Settings.System.CONTENT_URI, true, mFormatChangeObserver);
+ if (mFormatChangeObserver == null) {
+ mFormatChangeObserver = new FormatChangeObserver(this);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.CONTENT_URI, true, mFormatChangeObserver);
+ }
updateTime();
}
@@ -163,16 +198,19 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- if (!mAttached) return;
- mAttached = false;
+ mAttached--;
- if (mLive) {
+ if (mIntentReceiver != null) {
mContext.unregisterReceiver(mIntentReceiver);
}
- mContext.getContentResolver().unregisterContentObserver(
- mFormatChangeObserver);
- }
+ if (mFormatChangeObserver != null) {
+ mContext.getContentResolver().unregisterContentObserver(
+ mFormatChangeObserver);
+ }
+ mFormatChangeObserver = null;
+ mIntentReceiver = null;
+ }
void updateTime(Calendar c) {
mCalendar = c;
@@ -180,9 +218,7 @@
}
private void updateTime() {
- if (mLive) {
- mCalendar.setTimeInMillis(System.currentTimeMillis());
- }
+ mCalendar.setTimeInMillis(System.currentTimeMillis());
CharSequence newTime = DateFormat.format(mFormat, mCalendar);
mTimeDisplayBackground.setText(newTime);
@@ -195,8 +231,4 @@
? M24 : M12;
mAmPm.setShowAmPm(mFormat.equals(M12));
}
-
- void setLive(boolean live) {
- mLive = live;
- }
}
diff --git a/docs/html/sdk/android-3.0-highlights.jd b/docs/html/sdk/android-3.0-highlights.jd
new file mode 100644
index 0000000..ed49307
--- /dev/null
+++ b/docs/html/sdk/android-3.0-highlights.jd
@@ -0,0 +1,266 @@
+page.title=Android 3.0 Platform Highlights
+
+@jd:body
+
+
+<style type="text/css">
+#jd-content {
+ max-width:1200px;
+}
+#jd-content div.screenshot {
+ float:left;
+ clear:left;
+ padding:15px 30px 15px 0;
+}
+#jd-content div.video {
+ float:right;
+ padding:0 60px 40px;
+ margin-top:-15px;
+}
+#jd-content table.columns {
+ margin:0 0 1em 0;
+}
+#jd-content table.columns td {
+ padding:0;
+}
+#jd-content table.columns td+td {
+ padding:0 2em;
+}
+#jd-content table.columns td img {
+ margin:0;
+}
+#jd-content table.columns td+td>*:first-child {
+ margin-top:-2em;
+}
+.green {
+ color:#8db529;
+ font-weight:bold;
+}
+</style>
+
+
+
+
+
+
+<p>Welcome to Android 3.0!</p>
+
+<p>The Android 3.0 platform introduces many new and exciting features for users and developers.
+This document provides a glimpse of some of the new features and technologies, as delivered in the Android 3.0 Preview SDK. For more information about the SDK or how to download it, please see the <a href="{@docRoot}sdk/preview/index.html">Preview SDK</a> document.</p>
+
+<ul>
+ <li><a href="#UserFeatures">New User Features</a></li>
+ <li><a href="#DeveloperApis">New Developer Features</a></li>
+</ul>
+
+<h2 id="UserFeatures" style="clear:right">New User Features</h2>
+
+<div style="padding-top:0em;">
+<div style="margin-right:1em;margin-left:1em;float:right;padding-top:2em;"><a href="images/3.0/home_hero1_full.png" target="_android"><img src="images/3.0/home_hero1.png" alt="" height="280" /></a></div>
+
+<h3>New UI designed from the ground up for tablets</h3>
+
+<p>Android 3.0 is a new version of the Android platform that is specifically optimized for devices with larger screen sizes, particularly tablets. It introduces a brand new, truly virtual and “holographic” UI design, as well as an elegant, content-focused interaction model.</p>
+
+<p>Android 3.0 builds on the things people love most about Android — refined multitasking, rich notifications, Home screen customization, widgets, and more — and transforms them with a vibrant, 3D experience and deeper interactivity, making them familiar but even better than before.</p>
+
+<p>The new UI brings fresh paradigms for interaction, navigation, and customization and makes them available to all applications — even those built for earlier versions of the platform. Applications written for Android 3.0 are able to use an extended set of UI objects, powerful graphics, and media capabilities to engage users in new ways.</p>
+
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>System Bar, for global status and notifications</strong></p>
+
+<p>Across the system and in all applications, users have quick access to notifications, system status, and soft navigation buttons in a System Bar, available at the bottom of the screen. The System Bar is always present and is a key touchpoint for users, but in a new "lights out mode" can also be dimmed for full-screen viewing, such as for videos.</p>
+
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>Action Bar, for application control</strong></p>
+
+<p>In every application, users have access to contextual options, navigation, widgets, or other types of content in an Action Bar, displayed at the top of the screen. The Action Bar is always present when an application is in use, although its content, theme, and other properties are managed by the application rather than the system. The Action Bar is another key touchpoint for users, especially with action items and an overflow dropdown menu, which users frequently access in a similar manner in most applications. </p>
+
+</div>
+
+<div style="padding-top:0em;">
+<div style="margin-right:1em;float:right;margin-left:1em;"><a href="images/3.0/homescreen_cust_port_full.png" target="_android"><img src="images/3.0/homescreen_cust_port.png" alt="" height="280" /></a></div>
+
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>Customizable Home screens</strong></p>
+
+<p>Five customizable Home screens give users instant access to all parts of the system from any context. Each screen offers a large grid that maintains spatial arrangement in all orientations. Users can select and manipulate Home screen widgets, app shortcuts, and wallpapers using a dedicated visual layout mode. Visual cues and drop shadows improve visibility when adjusting the layout of shortcuts and widgets. Each Home screen also offers a familiar launcher for access to all installed applications, as well as a Search box for universal search of apps, contacts, media files, web content, and more.</p>
+
+</div>
+
+<div style="padding-top:0em;">
+<div style="margin-right:1.5em;float:left;"><a href="images/3.0/tasks_full.png" target="_android"><img src="images/3.0/tasks.png" alt="" height="280" /></a>
+
+<!--<p style="font-size:90%">Figure</p> --></div>
+
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>Recent Apps, for easy visual multitasking</strong></p>
+
+<p>Multitasking is a key strength of Android and it is central to the Android 3.0 experience. As users launch applications to handle various tasks, they can use the Recent Apps list in the System Bar to see the tasks underway and quickly jump from one application context to another. To help users rapidly identify the task associated with each app, the list shows a snapshot of its actual state when the user last viewed it.</p>
+
+</div>
+
+
+<h3>Redesigned keyboard</h3>
+
+<p>The Android soft keyboard is redesigned to make entering text fast and accurate on larger screen sizes. The keys are reshaped and repositioned for improved targeting, and new keys have been added, such as a Tab key, to provide richer and more efficient text input. Users can touch-hold keys to access menus of special characters and switch text/voice input modes from a button in the System Bar.</p>
+
+<div style="padding-top:1em;">
+<div style="margin-right:1em;float:right;"><a href="images/3.0/copy_full.png" target="_android"><img src="images/3.0/copy.png" alt="" height="180" /></a></div>
+
+
+<h3>Improved text selection, copy and paste</h3>
+
+<p>When entering or viewing text, a new UI lets users quickly select a word by press-hold and then adjust the selection area as needed by dragging a set of bounding arrows to new positions. Users can then select an action from the Action Bar, such as copy to the clipboard, share, paste, web search, or find. </p>
+
+
+<h3>New connectivity options</h3>
+
+<p>Android 3.0 includes new connectivity features that add versatility and convenience for users. Built-in support for Media/Photo Transfer Protocol lets users instantly sync media files with a USB-connected camera or desktop computer, without needing to mount a USB mass-storage device. Users can also connect full keyboards over either USB or Bluetooth, for a familiar text-input environment. For improved wi-fi connectivity, a new combo scan reduces scan times across bands and filters. New support for Bluetooth tethering means that more types of devices can share the network connection of an Android-powered device.</p>
+
+
+<h3>Updated set of standard apps</h3>
+
+<div style="padding-top:0em;">
+<div style="margin-right:1em;float:right;;padding-top:0em;margin-left:1em;"><a href="images/3.0/browser_full.png" target="_android"><img src="images/3.0/browser.png" alt="" height="200" /></a><br>
+<a href="images/3.0/camera_full.png" target="_android"><img src="images/3.0/camera_full.png" alt="" height="200" /></a></div>
+
+<p>The Android 3.0 platform includes an updated set of standard applications that are designed for use on larger screen devices. The sections below highlight some of the new features. </p>
+
+<strong>Browser</strong></p>
+
+<p>The browser includes new features that let users navigate and organize more efficiently. Multiple tabs replace browser windows and a new “incognito” mode allows anonymous browsing. Bookmarks and history are presented and managed in a single unified view. Users can now choose to automatically sign into Google sites on the browser with a supplied account and sync bookmarks with Google Chrome. New multitouch support is now available to JavaScript and plugins. Users can enjoy a better browsing experience at non-mobile sites through an improved zoom and viewport model, overflow scrolling, support for fixed positioning, and more.</p>
+
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>Camera and Gallery</strong></p>
+
+<p>The Camera application has been redesigned to take advantage of a larger screen for quick access to exposure, focus, flash, zoom, front-facing camera, and more. To let users capture scenes in new ways, it adds built-in support for time-lapse video recording. Gallery application lets users view albums and other collections in full-screen mode, with easy access to thumbnails for other photos in the collection. </p>
+
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>Contacts</strong></p>
+
+<p>The Contacts app uses a new two-pane UI and Fast Scroll to let users easily organize and locate contacts. The application offers improved formatting of international phone numbers as user types, based on home country and an international number parsing library. Contact information is presented in a card-like UI, making it easier for users to read and edit contacts.</p>
+
+<p style="margin-top:1em;margin-bottom:.75em;"><strong>Email</strong></p>
+
+<p>The Email application uses a new two-pane UI to make viewing and organizing messages more efficient. The app lets users select one or more messages, then select an action from the Action Bar, such as moving them to a folder. Users can sync attachments for later viewing and keep track of email using a home screen Widget.</p>
+
+</div>
+
+
+<h2 id="DeveloperApis" style="clear:both">New Developer Features</h2>
+
+<p>The Android 3.0 platform is designed specially to meet the unique needs of applications on devices with larger screen sizes. It offers all of the tools developers need to create incredible visual and interaction experiences on these devices.</p>
+
+ <ul>
+<li><a href="#ui">New UI framework for creating great tablet apps</a></li>
+<li><a href="#graphics">High-performance 2D and 3D graphics</a></li>
+<li><a href="#multicore">Support for multicore processor architectures</a></li>
+<li><a href="#multimedia">Rich multimedia and connectivity</a></li>
+<li><a href="#enterprise">Enhancements for enterprise</a></li>
+<li><a href="#compatibility">Compatibility with existing apps</a></li>
+</ul>
+
+<h3 id="ui">New UI Framework for creating great tablet apps</h3>
+
+<div style="padding-top:0em;">
+<div style="margin-right:1em;float:right;margin-left:1em;"><a href="images/3.0/contacts_full.png" target="_android"><img src="images/3.0/contacts.png" alt="" height="200" /></a></div>
+
+
+<p style="margin-top:.75em;margin-bottom:.75em;"><strong>Activity fragments, for greater control of content and design flexibility</strong></p>
+
+<p>Starting with Android 3.0, developers can break the Activities of their applications into subcomponents called Fragments, then combine them in a variety of ways to create a richer, more interactive experience. For example, an application can use a set of Fragments to create a true multipane UI, with the user being able to interact with each pane independently. Fragments can be added, removed, replaced, and animated inside an Activity dynamically, and they are modular and reusable across multiple Activities. Because they are modular, Fragments also offer an efficient way for developers to write applications that can run properly on both larger screen as well as smaller screen devices.</p>
+
+</div>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Redesigned UI widgets</strong></p>
+
+<p>Android 3.0 offers an updated set of UI widgets that developers can use to quickly add new types of content to their applications. The new UI widgets are redesigned for use on larger screens such as tablets and incorporate the new holographic UI theme. Several new widget types are available, including a 3D stack, search box, a date/time picker, number picker, calendar, popup menu, and others. Most of the redesigned UI widgets can now be used as remote views in application widgets displayed on the home screen. Applications written for earlier versions can inherit the new Widget designs and themes.</p>
+
+
+<div style="padding-top:0em;">
+<div style="margin-right:1.5em;float:left;margin-left:0em;"><a href="images/3.0/widgets.png" target="_android"><img src="images/3.0/widgets.png" alt="" height="200" target="_android" /></a></div>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Expanded Home screen widgets</strong></p>
+
+<p>Home screen widgets are popular with users because they offer fast access to application-specific data directly from the home screen. Android 3.0 lets developers take home screen widgets to the next level, offering more types of content and new modes of interaction with users. Developers can now use more standard UI widget types home screen widgets, including widgets that let users flip through collections of content as 3D stacks, grids, or lists. Users can interact with the home screen widgets in new ways, such as by using touch gestures to scroll and flip the content displayed in a widget. </p>
+
+</div>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Persistent Action Bar</strong></p>
+
+<p>The platform provides each application with its own instance of the Action Bar at the top of the screen, which the application can use to give the user quick access to contextual options, widgets, status, navigation, and more. The application can also customize the display theme of its Action Bar instance. The Action Bar lets developers expose more features of their applications to users in a familiar location, while also unifying the experience of using an application that spans multiple Activities or states.</p>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Richer notifications</strong></p>
+
+<p>Notifications are a key part of the Android user experience because they let applications show key updates and status information to users in real time. Android 3.0 extends this capability, letting developers include richer content and control more properties. A new builder class lets developers quickly create notifications that include large and small icons, a title, a priority flag, and any properties already available in previous versions. Notifications can offer more types of content by building on the expanded set of UI Widgets that are now available as remote Views.</p>
+
+<div style="padding-top:0em;">
+<div style="margin-right:1em;float:right;margin-left:1em;"><a href="images/3.0/mail_drag_full.png" target="_android"><img src="images/3.0/mail_drag.png" alt="" height="200" style="padding-top:1em;"/></a></div>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Multiselect, clipboard, and drag-and-drop</strong></p>
+
+<p>The platform offers convenient new interaction modes that developers can use. For managing collections of items in lists or grids, developers can offer a new multiselect mode that lets users choose multiple items for an action. Developers can also use a new system-wide Clipboard to let users easily copy any type of data into and out of their applications. To make it easier for users to manage and organize files, developers can now add drag-and-drop interaction through a DragEvent framework.</p>
+
+</div>
+
+
+<h3 id="graphics">High-performance 2D and 3D graphics</h3>
+
+<p style="margin-top:.75em;margin-bottom:.75em;"><strong>New animation framework</strong></p>
+
+<p>The platform includes a flexible new animation framework that lets developers easily animate the properties of UI elements such as Views, Widgets, Fragments, Drawables, or any arbitrary object. Animations can create fades or movement between states, loop an animated image or an existing animation, change colors, and much more. Adding animation to UI elements can add visual interest to an application and refine the user experience, to keep users engaged.</p>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Hardware-accelerated 2D graphics</strong></p>
+
+<p>Android 3.0 offers a new hardware-accelerated OpenGL renderer that gives a performance boost to many common graphics operations for applications running in the Android framework. When the renderer is enabled, most operations in Canvas, Paint, Xfermode, ColorFilter, Shader, and Camera are accelerated. Developers can control how hardware-acceleration is applied at every level, from enabling it globally in an application to enabling it in specific Activities and Views inside the application.</p>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Renderscript 3D graphics engine</strong></p>
+
+<p>Renderscript is a runtime 3D framework that provides both an API for building 3D scenes as well as a special, platform-independent shader language for maximum performance. Using Renderscript, you can accelerate graphics operations and data processing. Renderscript is an ideal way to create high-performance 3D effects for applications, wallpapers, carousels, and more.</p>
+
+
+<h3 id="multicore">Support for multicore processor architectures</h3>
+
+<p>Android 3.0 is the first version of the platform designed to run on either single or multicore processor architectures. A variety of changes in the Dalvik VM, Bionic library, and elsewhere add support for symmetric multiprocessing in multicore environments. These optimizations can benefit all applications, even those that are single-threaded. For example, with two active cores, a single-threaded application might still see a performance boost if the Dalvik garbage collector runs on the second core. The system will arrange for this automatically.</p>
+
+
+<h3 id="multimedia">Rich multimedia and connectivity</h3>
+
+<p style="margin-top:.75em;margin-bottom:.75em;"><strong>HTTP Live streaming</strong></p>
+
+<p>Applications can now pass an M3U playlist URL to the media framework to begin an HTTP Live streaming session. The media framework supports most of the HTTP Live streaming specification, including adaptive bit rate.</p>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Pluggable DRM framework</strong></p>
+
+<p>Android 3.0 includes an extensible DRM framework that lets applications manage protected content according to a variety of DRM mechanisms that may be available on the device. For application developers, the framework API offers an consistent, unified API that simplifies the management of protected content, regardless of the underlying DRM engines. </p>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>Digital media file transfer</strong></p>
+
+<p>The platform includes built-in support for Media/Picture Transfer Protocol (MTP/PTP) over USB, which lets users easily transfer any type of media files between devices and to a host computer. Developers can build on this support, creating applications that let users create or manage media files that they may want to transfer or share across devices. </p>
+
+<p style="margin-top:1.25em;margin-bottom:.75em;"><strong>More types of connectivity</strong></p>
+
+<p>The platform offers new connectivity that developers can build on. API support for Bluetooth A2DP and HSP profiles lets applications query Bluetooth profiles for connected devices, audio state, and more, then notify the user. For example, a music application can check connectivity and status and let the user know that music is playing through a stereo headset. Applications can also register to receive system broadcasts of pre-defined vendor-specific AT commands, such as Platronics Xevent. For example, an application could receive broadcasts that indicate a connected device's battery level and could notify the user or take other action as needed. Applications can also take advantage of the platform's new support for full keyboards connected by USB or Bluetooth. </p>
+
+
+<h3 id="enterprise">Enhancements for enterprise</h3>
+
+<p>In Android 3.0, developers of device administration applications can support new types of policies, including policies for encrypted storage, password expiration, password history, and password complex characters required. </p>
+
+<h3 id="compatibility">Compatibility with existing apps</h3>
+
+<p>Android 3.0 brings a new UI designed for tablets and other larger screen devices, but it also is fully compatible with applications developed for earlier versions of the platform, or for smaller screen sizes. Existing applications can seamlessly participate in the new holographic UI theme without code changes, by adding a single attribute in their manifest files. The platform emulates the Menu key, which is replaced by the overflow menu in the Action Bar in the new UI. Developers wanting to take fuller advantage of larger screen sizes can also create dedicated layouts and assets for larger screens and add them to their existing applications.</p>
+
+
+<h2>More information</h2>
+
+<div class="video">
+<object width="278" height="180">
+<param name="movie" value="http://www.youtube.com/v/hPUGNCIozp0?hl=en&fs=1"></param>
+<param name="allowFullScreen" value="true"></param><param name="allowscriptaccess"
+value="always"></param>
+<embed src="http://www.youtube.com/v/hPUGNCIozp0?hl=en&fs=1" type="application/x-shockwave-flash"
+allowscriptaccess="always" allowfullscreen="true" width="278" height="180"></embed>
+</object>
+</div>
+
+<p>For more information about the new developer APIs, see the Android 3.0 Platform notes in the SDK Preview documentation, available by download through the Android SDK Manager.</p>
+
+<p>For a video overview of platform features, see the Android 3.0 Sneak Peek. </p>
+
+
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index a83ca8e..0bb830c 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,9 +1,8 @@
page.title=ADT Plugin for Eclipse
-sdk.preview=0
-adt.zip.version=8.0.1
-adt.zip.download=ADT-8.0.1.zip
-adt.zip.bytes=8724909
-adt.zip.checksum=0e62185279083ddc01f18098ce7ba2d1
+adt.zip.version=9.0.0
+adt.zip.download=ADT_9.0.0.zip
+adt.zip.bytes=4433536
+adt.zip.checksum=bc2757f2a5a11d131390ce547bae154b
@jd:body
diff --git a/docs/html/sdk/images/3.0/browser.png b/docs/html/sdk/images/3.0/browser.png
new file mode 100644
index 0000000..5d3ba31
--- /dev/null
+++ b/docs/html/sdk/images/3.0/browser.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/browser_full.png b/docs/html/sdk/images/3.0/browser_full.png
new file mode 100644
index 0000000..495a23d
--- /dev/null
+++ b/docs/html/sdk/images/3.0/browser_full.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/camera.png b/docs/html/sdk/images/3.0/camera.png
new file mode 100644
index 0000000..a549182
--- /dev/null
+++ b/docs/html/sdk/images/3.0/camera.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/camera_full.png b/docs/html/sdk/images/3.0/camera_full.png
new file mode 100644
index 0000000..a549182
--- /dev/null
+++ b/docs/html/sdk/images/3.0/camera_full.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/contacts.png b/docs/html/sdk/images/3.0/contacts.png
new file mode 100644
index 0000000..0dcd164
--- /dev/null
+++ b/docs/html/sdk/images/3.0/contacts.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/contacts_full.png b/docs/html/sdk/images/3.0/contacts_full.png
new file mode 100644
index 0000000..829ad11
--- /dev/null
+++ b/docs/html/sdk/images/3.0/contacts_full.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/copy.png b/docs/html/sdk/images/3.0/copy.png
new file mode 100644
index 0000000..363aa8e
--- /dev/null
+++ b/docs/html/sdk/images/3.0/copy.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/copy_full.png b/docs/html/sdk/images/3.0/copy_full.png
new file mode 100644
index 0000000..a8db8a2
--- /dev/null
+++ b/docs/html/sdk/images/3.0/copy_full.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/home_hero1.png b/docs/html/sdk/images/3.0/home_hero1.png
new file mode 100644
index 0000000..c81e7ef
--- /dev/null
+++ b/docs/html/sdk/images/3.0/home_hero1.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/home_hero1_full.png b/docs/html/sdk/images/3.0/home_hero1_full.png
new file mode 100644
index 0000000..e280b81
--- /dev/null
+++ b/docs/html/sdk/images/3.0/home_hero1_full.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/homescreen_cust_port.png b/docs/html/sdk/images/3.0/homescreen_cust_port.png
new file mode 100644
index 0000000..ef7f5ab
--- /dev/null
+++ b/docs/html/sdk/images/3.0/homescreen_cust_port.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/homescreen_cust_port_full.png b/docs/html/sdk/images/3.0/homescreen_cust_port_full.png
new file mode 100644
index 0000000..22433a3e
--- /dev/null
+++ b/docs/html/sdk/images/3.0/homescreen_cust_port_full.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/mail_drag.png b/docs/html/sdk/images/3.0/mail_drag.png
new file mode 100644
index 0000000..6084caa
--- /dev/null
+++ b/docs/html/sdk/images/3.0/mail_drag.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/mail_drag_full.png b/docs/html/sdk/images/3.0/mail_drag_full.png
new file mode 100644
index 0000000..f99c612
--- /dev/null
+++ b/docs/html/sdk/images/3.0/mail_drag_full.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/tasks.png b/docs/html/sdk/images/3.0/tasks.png
new file mode 100644
index 0000000..9e82dcb
--- /dev/null
+++ b/docs/html/sdk/images/3.0/tasks.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/tasks_full.png b/docs/html/sdk/images/3.0/tasks_full.png
new file mode 100644
index 0000000..d2a2241
--- /dev/null
+++ b/docs/html/sdk/images/3.0/tasks_full.png
Binary files differ
diff --git a/docs/html/sdk/images/3.0/widgets.png b/docs/html/sdk/images/3.0/widgets.png
new file mode 100644
index 0000000..d847666
--- /dev/null
+++ b/docs/html/sdk/images/3.0/widgets.png
Binary files differ
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 4113463..499b31f 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,21 +1,21 @@
page.title=Android SDK
sdk.redirect=0
-sdk.win_installer=installer_r08-windows.exe
-sdk.win_installer_bytes=32746192
-sdk.win_installer_checksum=04ce87b10a8361a1f63cf2238bbc1ee3
+sdk.win_installer=installer_r09-windows.exe
+sdk.win_installer_bytes=32828818
+sdk.win_installer_checksum=a0185701ac0d635a4fbf8169ac949a3c5b3d31e0
-sdk.win_download=android-sdk_r08-windows.zip
-sdk.win_bytes=32696391
-sdk.win_checksum=3e0b08ade5bfa9624bce9ddc164a48cb
+sdk.win_download=android-sdk_r09-windows.zip
+sdk.win_bytes=32779808
+sdk.win_checksum=1a1bb8fad80bcc2dfbd00443b9a13e6b
-sdk.mac_download=android-sdk_r08-mac_86.zip
-sdk.mac_bytes=28797617
-sdk.mac_checksum=d2e392c4e4680cbf2dfd6dbf82b662c7
+sdk.mac_download=android-sdk_r09-mac_x86.zip
+sdk.mac_bytes=28829553
+sdk.mac_checksum=ef3102fdbbbbd9bf4d9b572624aa9dc1
-sdk.linux_download=android-sdk_r08-linux_86.tgz
-sdk.linux_bytes=26817291
-sdk.linux_checksum=3b626645b223d137d27beefbda0c94bc
+sdk.linux_download=android-sdk_r09-linux_x86.tgz
+sdk.linux_bytes=26917824
+sdk.linux_checksum=9fefac5ff85d329836439f6e77a78cae
@jd:body
diff --git a/docs/html/sdk/installing.jd b/docs/html/sdk/installing.jd
index e8d97e7..53d5515 100644
--- a/docs/html/sdk/installing.jd
+++ b/docs/html/sdk/installing.jd
@@ -1,5 +1,4 @@
page.title=Installing the SDK
-sdk.preview=0
@jd:body
diff --git a/docs/html/sdk/preview/index.jd b/docs/html/sdk/preview/index.jd
index 81b4ff6..edfa02b 100644
--- a/docs/html/sdk/preview/index.jd
+++ b/docs/html/sdk/preview/index.jd
@@ -1,4 +1,183 @@
-sdk.redirect=true
-
+page.title=Android 3.0 Preview SDK
@jd:body
+<p>Android 3.0 is the next major release of the Android platform and is optimized for tablet
+devices. We're offering a Preview SDK so you can get a head-start developing
+applications for it or simply optimize your existing application for upcoming
+tablets.</p>
+
+
+<h3>What is the Preview SDK?</h3>
+
+<p>The Android 3.0 Preview SDK is an early look at the upcoming version of Android 3.0, for
+developers only. </p>
+
+<p>The Preview SDK includes:</p>
+<ul>
+ <li>An early Android 3.0 system image for use in the Android emulator</li>
+ <li>An Android 3.0 library with non-final APIs</li>
+ <li>A new WXGA emulator skin for an extra large Android Virtual Device</li>
+ <li>New documentation for Android 3.0, including a complete API reference, new developer guides,
+and an API differences report between Android 3.0 and 2.3.</li>
+</ul>
+
+<div class="note">
+<p><strong>Be aware that:</strong></p>
+<ul>
+ <li>The APIs in the Preview SDK are <strong>not final</strong>. Some APIs may change in behavior
+or availability when the final SDK is made available.</li>
+ <li>You <strong>cannot</strong> publish an application that's built against the Preview
+SDK—you can only run an application built against the Preview SDK on the Android
+emulator.</li>
+ <li>The documentation on <a href="http://developer.android.com">developer.android.com</a>
+does <strong>not</strong> include the Android 3.0 documentation—to read the API reference and
+developer guides for Android 3.0, you must install the Android 3.0 Preview documentation from
+the AVD and SDK Manager.</li>
+</ul>
+</div>
+
+
+<p><b>About emulator performance</b></p>
+
+<p>Because the Android emulator must simulate the ARM instruction set architecture on your
+computer and the WXGA screen is significantly larger than what the emulator
+normally handles, emulator performance is much slower than usual. </p>
+
+<p>In particular, initializing the emulator can be slow and can take several
+minutes, depending on your hardware. When the emulator is booting there is
+limited user feedback, so please be patient and continue waiting until you see
+the home screen appear. </p>
+
+<p>We're working hard to resolve the performance issues in the emulator and it will improve in
+future releases. In the meantime, we wanted to give developers access to new APIs and an basic test
+environment as early as possible. </p>
+
+<p>Keeping in mind that performance on the emulator does not reflect the speed or performance of
+apps on actual devices running Android 3.0, developing and testing on the emulator is still an
+important tool in evaluating your application's appearance and functionality on the new platform.
+</p>
+
+
+
+
+
+<h3>What can I do with the preview?</h3>
+
+<p>The Preview SDK is intended for testing existing applications on the new platform and
+developing new applications with new Android 3.0 APIs.</p>
+
+<p>If you have an existing Android application, you don't <em>have to</em> do anything. Android
+applications are always forward-compatible. If your application is a good citizen of the Android
+APIs, your app should work fine on devices running Android 3.0 without any additional work. However,
+in order to ensure proper performance and provide users a better experience when running your
+application on an Android 3.0 tablet, we recommend that you perform the following:</p>
+
+<ol>
+ <li><b>Test your application on Android 3.0</b>
+ <p>Simply install the Android 3.0 preview in your Android SDK, create an AVD using the
+Android 3.0 system image, install your application, and run some tests.</p>
+ <p>As mentioned above, your application should perform as expected. You might, however,
+discover that your activity layouts are less than ideal on a large screen or some other aspects
+of your application don't behave the way you expect.</p>
+ </li>
+ <li><b>Inherit the new "Holographic" theme</b>
+ <p>Android 3.0 offers an updated set of UI widgets that are redesigned for use on larger screens
+such as tablets and incorporate the new holographic theme. Your existing application can inherit
+the new design simply by setting the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code <uses-sdk>}</a>
+element's {@code android:targetSdkVersion} attribute to {@code "Honeycomb"}.</p>
+ <p>If you do not update the {@code android:targetSdkVersion} attribute and the {@code
+android:minSdkVersion} is set to "9" or lower, then your application uses the widget designs
+from Android 2.3 and does <em>not</em> inherit the holographic theme.</p>
+ <p>In order for your application to match the rest of the system UI, we highly recommend you
+make this change to inherit the new widget styles and system theme. However, beware that doing so
+might conflict with color or text designs you applied to your application based on the previous
+system theme, so you should be sure to inspect your application UI when using the holographic
+theme.</p>
+ </li>
+ <li><b>Provide alternative layouts for extra large screens</b>
+ <p>As discussed in the guide to <a
+href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>, Android
+2.3 and above support the <code>xlarge</code> resource qualifier, which you should use to supply
+alternative layouts for extra large screens.</p>
+ <p>By providing alternative layouts for some of your activities when running on extra large
+screens, you can improve the user experience of your application on a tablet without using any
+new APIs.</p>
+ <p>For example, here are some things to consider when creating a new layout for tables:</p>
+ <ul>
+ <li>Landscape layout: The "normal" orientation for tablets is usually landscape (wide), so
+you should be sure that your activities offer an appropriate layout for such a wide viewing
+area.</li>
+ <li>Button position: Consider whether the position of the most common buttons in your UI are
+easily accessible while holding a tablet with two hands.</li>
+ </ul>
+ <p class="note"><strong>Note:</strong> You can add alternative resources for <em>xlarge</em>
+screens without changing your {@code minSdkVersion}. For example, if you add alternative layouts in
+<code>res/layout-xlarge/</code> and your application is compatible with older versions, such
+as Android 1.5—which doesn't support <em>xlarge</em> screens—this layout directory is
+simply ignored by those devices.</p>
+ </li>
+</ol>
+
+
+<p>Otherwise, if you want to develop a new application or upgrade your existing application to
+use APIs added in Android 3.0, we encourage you to get started by developing against the Android
+3.0 preview platform. You can get started the same way as you would for any other version of
+Android.</p>
+
+
+<p>To get started—whether testing an existing application or creating a new one—follow
+the procedure in the following section to install the Preview SDK.</p>
+
+
+
+<h3 id="Setup">How do I get it?</h3>
+
+<p>To get the Preview SDK, you can download it using the Android SDK and AVD Manager.</p>
+
+<p>If you're new to Android development, start by <a href="{@docRoot}sdk/index.html">downloading the
+Android SDK starter package</a>.</p>
+
+<p><a href="{@docRoot}sdk/adding-components.html#launching">Launch the Android SDK and AVD
+Manager</a> and install the following:</p>
+<ul>
+ <li>SDK Platform Android Honeycomb Preview</li>
+ <li>Android SDK Tools, revision 9</li>
+ <li>Android SDK Platform-tools, revision 2</li>
+ <li>Documentation for Android 'Honeycomb' Preview</li>
+ <li>Samples for SDK API Honeycomb Preview</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Be sure to install the documentation component for the
+Honeycomb Preview SDK. The API reference for the Android 3.0 API is <strong>not</strong> available
+online.</p>
+
+<p>Once you have installed these components, open your SDK directory and navigate to {@code
+docs/sdk/} and open {@code index.html} in your browser. </p>
+
+
+
+<h3 id="Issues">Known issues</h3>
+
+<p>The following known issues occur for Android 3.0 AVDs that are loaded in the emulator:</p>
+
+<ul>
+ <li>The emulator displays a rotated portrait screen while in landscape
+orientation. To view the screen correctly in landscape orientation, turn off the auto-rotate setting
+in <strong>Settings > Screen > Auto-rotate screen</strong>. Then use Ctrl-F11 to rotate the
+emulator.</li>
+ <li>You cannot take screenshots of an emulator screen. The Device Screen Capture window displays
+<strong>Screen not available</strong>.</li>
+ <li>GPS emulation is currently not supported.</li>
+ <li>When rotating the emulator screen by pressing Ctrl-F11, the screen turns green momentarily,
+then displays the normal interface.</li>
+ <li>The Dev Tools application sometimes crashes when trying to use the Package Browser
+feature.</li>
+</ul>
+
+
+<div class="special">
+ <p>For an overview of new features in Android 3.0, read the <a
+href="{@docRoot}sdk/android-3.0-highlights.html">Platform Highlights</a>.</p>
+</div>
+
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 7cf7b07..9b67fee 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -52,6 +52,16 @@
</ul>
</li><?cs
/if ?>
+ <?cs
+ if:sdk.preview ?>
+ <li><h2>Android 3.0 Preview</h2>
+ <ul>
+ <li><a href="<?cs var:toroot ?>sdk/android-3.0-highlights.html">Platform Highlights</a> <span
+class="new">new!</span></li>
+ <li><a href="<?cs var:toroot ?>sdk/preview/index.html">SDK</a> <span class="new">new!</span></li>
+ </ul>
+ </li><?cs
+ /if ?>
<li>
<h2>
<span class="en">Downloadable SDK Components</span>
@@ -158,10 +168,7 @@
<span class="en">OEM USB Drivers</span>
</a></li>
<li><a href="<?cs var:toroot ?>sdk/requirements.html">SDK System Requirements</a></li>
- <!-- <li><a href="<?cs var:toroot ?>sdk/RELEASENOTES.html">SDK Release
- Notes</a></li> -->
- <li><a href="<?cs var:toroot ?>sdk/older_releases.html">SDK
- Archives</a></li>
+ <li><a href="<?cs var:toroot ?>sdk/older_releases.html">SDK Archives</a></li>
</ul>
</li>
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index 212d3c0..97ca8ab0 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -103,8 +103,10 @@
<li>The LogCat view in DDMS now properly displays UTF-8 characters.</li>
<li>The SDK Manager is more reliable on Windows. For details on the improvements, see the
<a href="http://tools.android.com/recent/sdkmanagerfixes">Android Tools Project Site</a>. </li>
- <li>If you enabled snapshots for an AVD, they are automatically captured. The emulator also now restores to the state when
- it last closed almost instantly.</li>
+ <li>Early look at the new snapshot feature: To improve startup time for the emulator, you can
+enable snapshots for the system state. The emulator will then restore to the state when it last
+closed almost instantly. <strong>Note:</strong> The snapshot feature is still under active
+development and might not always perform as expected.</li>
<li>Fixed the missing JAR file error that prevented <code>draw9patch</code> from running.</li>
<li>Fixed the Windows launch scripts <code>hierarchyviewer</code> and <code>ddms</code> to support
the new location of <code>adb</code>.</li>
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index 2216824..01ae23f 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -266,13 +266,13 @@
int32_t mode = data.readInt32();
status_t res = turnElectronBeamOff(mode);
reply->writeInt32(res);
- }
+ } break;
case TURN_ELECTRON_BEAM_ON: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
int32_t mode = data.readInt32();
status_t res = turnElectronBeamOn(mode);
reply->writeInt32(res);
- }
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index a660429..43571cf 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -219,8 +219,13 @@
}
for (uint32_t i = 0; i < mCaptureSize; i += 2) {
- fft[i] = workspace[i >> 1] >> 24;
- fft[i + 1] = workspace[i >> 1] >> 8;
+ short tmp = workspace[i >> 1] >> 21;
+ while (tmp > 127 || tmp < -128) tmp >>= 1;
+ fft[i] = tmp;
+ tmp = workspace[i >> 1];
+ tmp >>= 5;
+ while (tmp > 127 || tmp < -128) tmp >>= 1;
+ fft[i + 1] = tmp;
}
return NO_ERROR;
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index 5c20811..2253eb2 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -25,7 +25,8 @@
<application>
<uses-library android:name="android.test.runner" />
<activity android:label="@string/app_name"
- android:name="MediaFrameworkTest">
+ android:name="MediaFrameworkTest"
+ android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml
index c4bca61..bb1cf23 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml
@@ -38,6 +38,47 @@
android:layout_marginLeft="20dip"
android:orientation="vertical"
android:background="@*android:drawable/dialog_full_holo_dark">
+ <!-- Hard keyboard switch -->
+ <LinearLayout
+ android:id="@+id/hard_keyboard_section"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal">
+ <TextView
+ android:id="@+id/use_physical_keyboard_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:background="?android:attr/selectableItemBackground"
+ android:orientation="vertical"
+ android:paddingRight="6dip"
+ android:paddingLeft="30dip"
+ android:paddingTop="5dip"
+ android:paddingBottom="5dip"
+ android:gravity="center_vertical"
+ android:singleLine="true"
+ android:text="@string/status_bar_use_physical_keyboard"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:ellipsize="marquee" />
+ <Switch
+ android:id="@+id/hard_keyboard_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginRight="16dip" />
+ </LinearLayout>
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="@android:drawable/divider_horizontal_dark" />
+ </LinearLayout>
+
+ <!-- Input method list -->
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -50,6 +91,8 @@
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
+
+ <!-- Configure input methods -->
<TextView
android:id="@+id/ime_settings_shortcut"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index a550a0b..c38abdd 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -43,4 +43,5 @@
<!-- outdated translation 5550538721034982973 --> <string name="recent_tasks_app_label" msgid="3796483981246752469">"Google Apps"</string>
<!-- outdated translation 8017158699581472359 --> <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth anclado"</string>
<!-- outdated translation 3875357213648023768 --> <string name="status_bar_input_method_settings_configure_input_methods" msgid="737483394044014246">"Configurar métodos de entrada"</string>
+ <string name="status_bar_use_physical_keyboard">"Usar un teclado externo"</string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 53d06c0..0923570 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -112,4 +112,7 @@
<string name="bluetooth_tethered">Bluetooth tethered</string>
<!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] -->
<string name="status_bar_input_method_settings_configure_input_methods">Configure input methods</string>
+
+ <!-- Label of a toggle switch to disable use of the physical keyboard in favor of the IME. [CHAR LIMIT=25] -->
+ <string name="status_bar_use_physical_keyboard">Use physical keyboard</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 76aa793..d55a7c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -56,6 +56,7 @@
private static final int MSG_SHOW_MENU = 0x00080000;
private static final int MSG_SHOW_IME_BUTTON = 0x00090000;
+ private static final int MSG_SET_HARD_KEYBOARD_STATUS = 0x000a0000;
private StatusBarIconList mList;
private Callbacks mCallbacks;
@@ -83,6 +84,7 @@
public void setLightsOn(boolean on);
public void setMenuKeyVisible(boolean visible);
public void setImeWindowStatus(IBinder token, int vis, int backDisposition);
+ public void setHardKeyboardStatus(boolean available, boolean enabled);
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -173,6 +175,14 @@
}
}
+ public void setHardKeyboardStatus(boolean available, boolean enabled) {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_SET_HARD_KEYBOARD_STATUS);
+ mHandler.obtainMessage(MSG_SET_HARD_KEYBOARD_STATUS,
+ available ? 1 : 0, enabled ? 1 : 0).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -236,6 +246,9 @@
case MSG_SHOW_IME_BUTTON:
mCallbacks.setImeWindowStatus((IBinder)msg.obj, msg.arg1, msg.arg2);
break;
+ case MSG_SET_HARD_KEYBOARD_STATUS:
+ mCallbacks.setHardKeyboardStatus(msg.arg1 != 0, msg.arg2 != 0);
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
index da8e831..23ae823 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
@@ -67,7 +67,7 @@
mCommandQueue = new CommandQueue(this, iconList);
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- int[] switches = new int[5];
+ int[] switches = new int[7];
ArrayList<IBinder> binders = new ArrayList<IBinder>();
try {
mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
@@ -81,6 +81,7 @@
setMenuKeyVisible(switches[2] != 0);
// StatusBarManagerService has a back up of IME token and it's restored here.
setImeWindowStatus(binders.get(0), switches[3], switches[4]);
+ setHardKeyboardStatus(switches[5] != 0, switches[6] != 0);
// Set up the initial icon state
int N = iconList.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 9505391..1e46246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1021,6 +1021,8 @@
// Not supported
public void setMenuKeyVisible(boolean visible) { }
public void setImeWindowStatus(IBinder token, int vis, int backDisposition) { }
+ @Override
+ public void setHardKeyboardStatus(boolean available, boolean enabled) { }
private class Launcher implements View.OnClickListener {
private PendingIntent mIntent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index 136f4a94..6ab03e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Slog;
import android.widget.TextView;
@@ -27,7 +28,6 @@
import android.view.View;
import android.view.ViewParent;
-import java.text.DateFormat;
import java.util.Date;
public final class DateView extends TextView {
@@ -86,8 +86,11 @@
}
private final void updateClock() {
+ final Context context = getContext();
Date now = new Date();
- setText(DateFormat.getDateInstance(DateFormat.FULL).format(now));
+ CharSequence dow = DateFormat.format("EEEE", now);
+ CharSequence date = DateFormat.getMediumDateFormat(getContext()).format(now);
+ setText(dow + "\n" + date);
}
private boolean isVisible() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index d3f4703..a4c153f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -146,6 +146,7 @@
filter.addAction(Telephony.Intents.SPN_STRINGS_UPDATED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
+ filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
context.registerReceiver(this, filter);
// yuck
@@ -197,6 +198,8 @@
action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
updateConnectivity(intent);
refreshViews();
+ } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
+ refreshViews();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
index f131111..100ed55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
@@ -17,32 +17,23 @@
package com.android.systemui.statusbar.tablet;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.provider.Settings;
-import android.util.Log;
import android.util.AttributeSet;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import android.view.View;
import android.widget.ImageView;
import com.android.systemui.R;
import java.util.List;
-import java.util.Map;
public class InputMethodButton extends ImageView {
private static final String TAG = "StatusBar/InputMethodButton";
private static final boolean DEBUG = false;
- private static final int ID_IME_SWITCH_BUTTON = R.id.imeSwitchButton;
- // IME shortcut button is disabled.
- private static final int ID_IME_SHORTCUT_BUTTON = 0;
-
// These values are defined in Settings application.
private static final int ID_IME_BUTTON_VISIBILITY_AUTO = 0;
private static final int ID_IME_BUTTON_VISIBILITY_ALWAYS_SHOW = 1;
@@ -55,8 +46,7 @@
private IBinder mToken;
private boolean mShowButton = false;
private boolean mScreenLocked = false;
- private InputMethodInfo mShortcutInfo;
- private InputMethodSubtype mShortcutSubtype;
+ private boolean mHardKeyboardAvailable;
public InputMethodButton(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -65,26 +55,6 @@
mId = getId();
// IME hookup
mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- // TODO: read the current icon & visibility state directly from the service
-
- // TODO: register for notifications about changes to visibility & subtype from service
-
- setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- switch (mId) {
- case ID_IME_SWITCH_BUTTON:
- mImm.showInputMethodPicker();
- break;
- case ID_IME_SHORTCUT_BUTTON:
- if (mToken != null && mShortcutInfo != null) {
- mImm.setInputMethodAndSubtype(
- mToken, mShortcutInfo.getId(), mShortcutSubtype);
- }
- break;
- }
- }
- });
}
@Override
@@ -94,57 +64,17 @@
refreshStatusIcon();
}
- // TODO: Need to show an appropriate drawable for this shortcut button,
- // if there are two or more shortcut input methods contained in this button.
- // And need to add other methods to handle multiple shortcuts as appropriate.
- private Drawable getShortcutInputMethodAndSubtypeDrawable() {
- Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts =
- mImm.getShortcutInputMethodsAndSubtypes();
- if (shortcuts.size() > 0) {
- for (InputMethodInfo imi: shortcuts.keySet()) {
- List<InputMethodSubtype> subtypes = shortcuts.get(imi);
- // TODO: Returns the first found IMI for now. Should handle all shortcuts as
- // appropriate.
- mShortcutInfo = imi;
- // TODO: Pick up the first found subtype for now. Should handle all subtypes
- // as appropriate.
- mShortcutSubtype = subtypes.size() > 0 ? subtypes.get(0) : null;
- return getSubtypeIcon(mShortcutInfo, mShortcutSubtype);
- }
- }
- return null;
- }
-
- private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) {
- final PackageManager pm = getContext().getPackageManager();
- if (imi != null) {
- if (DEBUG) {
- Log.d(TAG, "Update icons of IME: " + imi.getPackageName());
- }
- if (subtype != null) {
- return pm.getDrawable(imi.getPackageName(), subtype.getIconResId(),
- imi.getServiceInfo().applicationInfo);
- } else if (imi.getSubtypeCount() > 0) {
- return pm.getDrawable(imi.getPackageName(),
- imi.getSubtypeAt(0).getIconResId(),
- imi.getServiceInfo().applicationInfo);
- } else {
- try {
- return pm.getApplicationInfo(imi.getPackageName(), 0).loadIcon(pm);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "IME can't be found: " + imi.getPackageName());
- }
- }
- }
- return null;
- }
-
// Display IME switcher icon only when all of the followings are true:
// * There is only one enabled IME on the device. (Note that the IME should be the system IME)
// * There are no explicitly enabled (by the user) subtypes of the IME, or the IME doesn't have
// its subtypes at all
private boolean needsToShowIMEButton() {
if (!mShowButton || mScreenLocked) return false;
+
+ if (mHardKeyboardAvailable) {
+ return true;
+ }
+
List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
final int size = imis.size();
final int visibility = loadInputMethodSelectorVisibility();
@@ -170,17 +100,7 @@
} else {
setVisibility(View.VISIBLE);
}
- Drawable icon = null;
- switch (mId) {
- case ID_IME_SHORTCUT_BUTTON:
- icon = getShortcutInputMethodAndSubtypeDrawable();
- break;
- }
- if (icon == null) {
- mIcon.setImageResource(R.drawable.ic_sysbar_ime);
- } else {
- mIcon.setImageDrawable(icon);
- }
+ mIcon.setImageResource(R.drawable.ic_sysbar_ime);
}
private int loadInputMethodSelectorVisibility() {
@@ -200,6 +120,13 @@
refreshStatusIcon();
}
+ public void setHardKeyboardStatus(boolean available) {
+ if (mHardKeyboardAvailable != available) {
+ mHardKeyboardAvailable = available;
+ refreshStatusIcon();
+ }
+ }
+
public void setScreenLocked(boolean locked) {
mScreenLocked = locked;
refreshStatusIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index 474ef45..502e0fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -23,11 +23,13 @@
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
+import android.os.RemoteException;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
+import android.util.Slog;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodInfo;
@@ -36,6 +38,7 @@
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
+import android.widget.Switch;
import android.widget.TextView;
import java.util.Comparator;
@@ -45,6 +48,7 @@
import java.util.Set;
import java.util.TreeMap;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, OnClickListener {
@@ -73,6 +77,11 @@
private IBinder mToken;
private InputMethodButton mInputMethodSwitchButton;
private LinearLayout mInputMethodMenuList;
+ private boolean mHardKeyboardAvailable;
+ private boolean mHardKeyboardEnabled;
+ private OnHardKeyboardEnabledChangeListener mHardKeyboardEnabledChangeListener;
+ private LinearLayout mHardKeyboardSection;
+ private Switch mHardKeyboardSwitch;
private PackageManager mPackageManager;
private String mEnabledInputMethodAndSubtypesCacheStr;
private String mLastSystemLocaleString;
@@ -107,6 +116,11 @@
mIntentFilter.addDataScheme("package");
}
+ public void setHardKeyboardEnabledChangeListener(
+ OnHardKeyboardEnabledChangeListener listener) {
+ mHardKeyboardEnabledChangeListener = listener;
+ }
+
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
@@ -128,6 +142,9 @@
@Override
public void onFinishInflate() {
mInputMethodMenuList = (LinearLayout) findViewById(R.id.input_method_menu_list);
+ mHardKeyboardSection = (LinearLayout) findViewById(R.id.hard_keyboard_section);
+ mHardKeyboardSwitch = (Switch) findViewById(R.id.hard_keyboard_switch);
+ mHardKeyboardSwitch.setOnClickListener(this);
mConfigureImeShortcut = ((View) findViewById(R.id.ime_settings_shortcut));
mConfigureImeShortcut.setOnClickListener(this);
// TODO: If configurations for IME are not changed, do not update
@@ -162,7 +179,9 @@
if (view == mConfigureImeShortcut) {
showConfigureInputMethods();
onFinishPanel(true);
- return;
+ } else if (view == mHardKeyboardSwitch) {
+ mHardKeyboardEnabled = mHardKeyboardSwitch.isChecked();
+ mHardKeyboardEnabledChangeListener.onHardKeyboardEnabledChange(mHardKeyboardEnabled);
}
}
@@ -239,6 +258,8 @@
}
private void updateUiElements() {
+ updateHardKeyboardSection();
+
// TODO: Reuse subtype views.
mInputMethodMenuList.removeAllViews();
mRadioViewAndImiMap.clear();
@@ -278,6 +299,23 @@
}
}
+ public void setHardKeyboardStatus(boolean available, boolean enabled) {
+ if (mHardKeyboardAvailable != available || mHardKeyboardEnabled != enabled) {
+ mHardKeyboardAvailable = available;
+ mHardKeyboardEnabled = enabled;
+ updateHardKeyboardSection();
+ }
+ }
+
+ private void updateHardKeyboardSection() {
+ if (mHardKeyboardAvailable) {
+ mHardKeyboardSection.setVisibility(View.VISIBLE);
+ mHardKeyboardSwitch.setChecked(mHardKeyboardEnabled);
+ } else {
+ mHardKeyboardSection.setVisibility(View.GONE);
+ }
+ }
+
// Turn on the selected radio button when the user chooses the item
private Pair<InputMethodInfo, InputMethodSubtype> updateRadioButtonsByView(View selectedView) {
Pair<InputMethodInfo, InputMethodSubtype> selectedImiAndSubtype = null;
@@ -423,4 +461,8 @@
}
mPackageChanged = true;
}
+
+ public interface OnHardKeyboardEnabledChangeListener {
+ public void onHardKeyboardEnabledChange(boolean enabled);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 1ac16de..715bb83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -76,7 +76,8 @@
import com.android.systemui.recent.RecentApplicationsActivity;
public class TabletStatusBar extends StatusBar implements
- HeightReceiver.OnBarHeightChangedListener {
+ HeightReceiver.OnBarHeightChangedListener,
+ InputMethodsPanel.OnHardKeyboardEnabledChangeListener {
public static final boolean DEBUG = false;
public static final String TAG = "TabletStatusBar";
@@ -269,6 +270,7 @@
// Input methods Panel
mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
R.layout.status_bar_input_methods_panel, null);
+ mInputMethodsPanel.setHardKeyboardEnabledChangeListener(this);
mInputMethodsPanel.setVisibility(View.GONE);
mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
@@ -909,6 +911,25 @@
}
}
+ @Override
+ public void setHardKeyboardStatus(boolean available, boolean enabled) {
+ if (DEBUG) {
+ Slog.d(TAG, "Set hard keyboard status: available=" + available
+ + ", enabled=" + enabled);
+ }
+ mInputMethodSwitchButton.setHardKeyboardStatus(available);
+ updateNotificationIcons();
+ mInputMethodsPanel.setHardKeyboardStatus(available, enabled);
+ }
+
+ @Override
+ public void onHardKeyboardEnabledChange(boolean enabled) {
+ try {
+ mBarService.setHardKeyboardEnabled(enabled);
+ } catch (RemoteException ex) {
+ }
+ }
+
private boolean isImmersive() {
try {
return ActivityManagerNative.getDefault().isTopActivityImmersive();
diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
index 840c5e1..c4feefd 100644
--- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java
@@ -62,8 +62,8 @@
*/
private static final int AWAKE_POKE_MILLIS = 30000;
- private final KeyguardScreenCallback mCallback;
- private final LockPatternUtils mLockPatternUtils;
+ private KeyguardScreenCallback mCallback;
+ private LockPatternUtils mLockPatternUtils;
private KeyguardUpdateMonitor mUpdateMonitor;
private TextView mTopHeader;
@@ -159,7 +159,10 @@
if (mCheckingDialog != null) {
mCheckingDialog.hide();
}
- mUpdateMonitor.removeCallback(this);
+ mUpdateMonitor.removeCallback(this); // this must be first
+ mCallback = null;
+ mLockPatternUtils = null;
+ mUpdateMonitor = null;
}
/** {@inheritDoc} */
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index 32c016d..edab690 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -229,8 +229,8 @@
mKeyguardHost.postDelayed(new Runnable() {
public void run() {
synchronized (KeyguardViewManager.this) {
- mKeyguardHost.removeView(lastView);
lastView.cleanUp();
+ mKeyguardHost.removeView(lastView);
}
}
}, 500);
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 822be46..886b85f 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -495,8 +495,10 @@
public void cleanUp() {
((KeyguardScreen) mLockScreen).onPause();
((KeyguardScreen) mLockScreen).cleanUp();
+ this.removeView(mLockScreen);
((KeyguardScreen) mUnlockScreen).onPause();
((KeyguardScreen) mUnlockScreen).cleanUp();
+ this.removeView(mUnlockScreen);
}
private boolean isSecure() {
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 1b810d5..2bc57b5 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -59,9 +59,9 @@
private Status mStatus = Status.Normal;
- private final LockPatternUtils mLockPatternUtils;
- private final KeyguardUpdateMonitor mUpdateMonitor;
- private final KeyguardScreenCallback mCallback;
+ private LockPatternUtils mLockPatternUtils;
+ private KeyguardUpdateMonitor mUpdateMonitor;
+ private KeyguardScreenCallback mCallback;
private SlidingTab mSlidingTab;
private TextView mScreenLocked;
@@ -659,7 +659,10 @@
/** {@inheritDoc} */
public void cleanUp() {
- mUpdateMonitor.removeCallback(this);
+ mUpdateMonitor.removeCallback(this); // this must be first
+ mLockPatternUtils = null;
+ mUpdateMonitor = null;
+ mCallback = null;
}
/** {@inheritDoc} */
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index 6815d50..6c6c2cc8 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -62,9 +62,9 @@
private int mTotalFailedPatternAttempts = 0;
private CountDownTimer mCountdownTimer = null;
- private final LockPatternUtils mLockPatternUtils;
- private final KeyguardUpdateMonitor mUpdateMonitor;
- private final KeyguardScreenCallback mCallback;
+ private LockPatternUtils mLockPatternUtils;
+ private KeyguardUpdateMonitor mUpdateMonitor;
+ private KeyguardScreenCallback mCallback;
/**
* whether there is a fallback option available when the pattern is forgotten.
@@ -362,6 +362,9 @@
/** {@inheritDoc} */
public void cleanUp() {
mUpdateMonitor.removeCallback(this);
+ mLockPatternUtils = null;
+ mUpdateMonitor = null;
+ mCallback = null;
}
@Override
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index e4086c4..2c81c34 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -1835,7 +1835,8 @@
AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) &&
- (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) &&
+ ((getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) ||
+ (stream == AudioSystem::SYSTEM)) &&
streamDesc.mCanBeMuted) {
volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
// when the phone is ringing we must consider that music could have been paused just before
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 877f559..586d222 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1057,7 +1057,8 @@
final boolean haveHardKeyboard = conf.keyboard
!= Configuration.KEYBOARD_NOKEYS;
final boolean hardKeyShown = haveHardKeyboard
- && conf.hardKeyboardHidden != Configuration.KEYBOARDHIDDEN_YES;
+ && conf.hardKeyboardHidden
+ != Configuration.HARDKEYBOARDHIDDEN_YES;
mImeWindowVis = (mInputShown || hardKeyShown) ? (
InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE)
: 0;
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 5e1e7d5..436eff0 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -80,7 +80,7 @@
private static final boolean LOCAL_LOGD = false;
private static final boolean DEBUG_UNMOUNT = false;
private static final boolean DEBUG_EVENTS = false;
- private static final boolean DEBUG_OBB = true;
+ private static final boolean DEBUG_OBB = false;
private static final String TAG = "MountService";
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 5806de2..d75aef6 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -8043,6 +8043,14 @@
sharedUser = orig.sharedUser;
}
+ public void copyFrom(PackageSetting base) {
+ super.copyFrom((PackageSettingBase) base);
+
+ userId = base.userId;
+ sharedUser = base.sharedUser;
+ pkg = base.pkg;
+ }
+
@Override
public String toString() {
return "PackageSetting{"
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 1a2f867..5ada77b 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -53,11 +53,13 @@
* if they are local, that they just enqueue messages to not deadlock.
*/
public class StatusBarManagerService extends IStatusBarService.Stub
+ implements WindowManagerService.OnHardKeyboardStatusChangeListener
{
static final String TAG = "StatusBarManagerService";
static final boolean SPEW = false;
final Context mContext;
+ final WindowManagerService mWindowManager;
Handler mHandler = new Handler();
NotificationCallbacks mNotificationCallbacks;
volatile IStatusBar mBar;
@@ -103,8 +105,10 @@
/**
* Construct the service, add the status bar view to the window manager
*/
- public StatusBarManagerService(Context context) {
+ public StatusBarManagerService(Context context, WindowManagerService windowManager) {
mContext = context;
+ mWindowManager = windowManager;
+ mWindowManager.setOnHardKeyboardStatusChangeListener(this);
final Resources res = context.getResources();
mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons));
@@ -320,6 +324,28 @@
}
}
+ public void setHardKeyboardEnabled(final boolean enabled) {
+ mHandler.post(new Runnable() {
+ public void run() {
+ mWindowManager.setHardKeyboardEnabled(enabled);
+ }
+ });
+ }
+
+ @Override
+ public void onHardKeyboardStatusChange(final boolean available, final boolean enabled) {
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (mBar != null) {
+ try {
+ mBar.setHardKeyboardStatus(available, enabled);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+ });
+ }
+
private void enforceStatusBar() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR,
"StatusBarManagerService");
@@ -335,7 +361,6 @@
"StatusBarManagerService");
}
-
// ================================================================================
// Callbacks from the status bar service.
// ================================================================================
@@ -363,6 +388,8 @@
switches[4] = mImeBackDisposition;
binders.add(mImeToken);
}
+ switches[5] = mWindowManager.isHardKeyboardAvailable() ? 1 : 0;
+ switches[6] = mWindowManager.isHardKeyboardEnabled() ? 1 : 0;
}
/**
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 978946f..92ec1da 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -248,7 +248,7 @@
try {
Slog.i(TAG, "Status Bar");
- statusBar = new StatusBarManagerService(context);
+ statusBar = new StatusBarManagerService(context, wm);
ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting StatusBarManagerService", e);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index faaa28d7..779e0ad 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -454,6 +454,10 @@
WindowState mInputMethodWindow = null;
final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
+ boolean mHardKeyboardAvailable;
+ boolean mHardKeyboardEnabled;
+ OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
+
final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
// If non-null, this is the currently visible window that is associated
@@ -5753,13 +5757,13 @@
mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
} else {
mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
-
- // If this screen is wider than normal HVGA, or taller
- // than FWVGA, then for old apps we want to run in size
- // compatibility mode.
- if (shortSize > 321 || longSize > 570) {
- mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
- }
+ }
+
+ // If this screen is wider than normal HVGA, or taller
+ // than FWVGA, then for old apps we want to run in size
+ // compatibility mode.
+ if (shortSize > 321 || longSize > 570) {
+ mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
}
// Is this a long screen?
@@ -5776,9 +5780,64 @@
config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
mPolicy.adjustConfigurationLw(config);
+
+ // Adjust the hard keyboard configuration based on whether the hard keyboard is enabled.
+ boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
+ if (hardKeyboardAvailable != mHardKeyboardAvailable) {
+ mHardKeyboardAvailable = hardKeyboardAvailable;
+ mHardKeyboardEnabled = hardKeyboardAvailable;
+
+ mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ }
+ if (!mHardKeyboardEnabled) {
+ config.keyboard = Configuration.KEYBOARD_NOKEYS;
+ config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
+ }
return true;
}
+ public boolean isHardKeyboardAvailable() {
+ synchronized (mWindowMap) {
+ return mHardKeyboardAvailable;
+ }
+ }
+
+ public boolean isHardKeyboardEnabled() {
+ synchronized (mWindowMap) {
+ return mHardKeyboardEnabled;
+ }
+ }
+
+ public void setHardKeyboardEnabled(boolean enabled) {
+ synchronized (mWindowMap) {
+ if (mHardKeyboardEnabled != enabled) {
+ mHardKeyboardEnabled = enabled;
+ mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
+ }
+ }
+ }
+
+ public void setOnHardKeyboardStatusChangeListener(
+ OnHardKeyboardStatusChangeListener listener) {
+ synchronized (mWindowMap) {
+ mHardKeyboardStatusChangeListener = listener;
+ }
+ }
+
+ void notifyHardKeyboardStatusChange() {
+ final boolean available, enabled;
+ final OnHardKeyboardStatusChangeListener listener;
+ synchronized (mWindowMap) {
+ listener = mHardKeyboardStatusChangeListener;
+ available = mHardKeyboardAvailable;
+ enabled = mHardKeyboardEnabled;
+ }
+ if (listener != null) {
+ listener.onHardKeyboardStatusChange(available, enabled);
+ }
+ }
+
// -------------------------------------------------------------
// Drag and drop
// -------------------------------------------------------------
@@ -8869,6 +8928,7 @@
public static final int REPORT_WINDOWS_CHANGE = 19;
public static final int DRAG_START_TIMEOUT = 20;
public static final int DRAG_END_TIMEOUT = 21;
+ public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
private Session mLastReportedHold;
@@ -9242,6 +9302,11 @@
}
break;
}
+
+ case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
+ notifyHardKeyboardStatusChange();
+ break;
+ }
}
}
}
@@ -11988,4 +12053,8 @@
return Animation.ZORDER_TOP;
}
}
+
+ public interface OnHardKeyboardStatusChangeListener {
+ public void onHardKeyboardStatusChange(boolean available, boolean enabled);
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 4424e5b..88d9436 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -402,7 +402,6 @@
/** Current network is eHRPD */
public static final int NETWORK_TYPE_EHRPD = 14;
-
/**
* Returns a constant indicating the radio technology (network type)
* currently in use on the device for data transmission.
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 43fae69..7abae09 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -905,6 +905,8 @@
public boolean getMute() {
if (hasActiveFgCall()) {
return getActiveFgCall().getPhone().getMute();
+ } else if (hasActiveBgCall()) {
+ return getFirstActiveBgCall().getPhone().getMute();
}
return false;
}
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 9479a2d..91b19a9 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -434,7 +434,6 @@
mWakeLock.release();
}
}
-
break;
}
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index f9bc0e9..7373cbb 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -309,7 +309,9 @@
}
public boolean getMute() {
- return foregroundCall.getMute();
+ return (foregroundCall.getState().isAlive()
+ ? foregroundCall.getMute()
+ : backgroundCall.getMute());
}
public Call getForegroundCall() {