diff options
70 files changed, 2462 insertions, 964 deletions
@@ -121,11 +121,11 @@ LOCAL_SRC_FILES += \ core/java/android/nfc/ILlcpConnectionlessSocket.aidl \ core/java/android/nfc/ILlcpServiceSocket.aidl \ core/java/android/nfc/ILlcpSocket.aidl \ - core/java/android/nfc/INdefTag.aidl \ core/java/android/nfc/INfcAdapter.aidl \ core/java/android/nfc/INfcTag.aidl \ core/java/android/nfc/IP2pInitiator.aidl \ core/java/android/nfc/IP2pTarget.aidl \ + core/java/android/nfc/INfcSecureElement.aidl \ core/java/android/os/IHardwareService.aidl \ core/java/android/os/IMessenger.aidl \ core/java/android/os/INetworkManagementService.aidl \ @@ -254,7 +254,6 @@ aidl_files := \ frameworks/base/core/java/android/nfc/NdefMessage.aidl \ frameworks/base/core/java/android/nfc/NdefRecord.aidl \ frameworks/base/core/java/android/nfc/Tag.aidl \ - frameworks/base/core/java/android/nfc/NdefTag.aidl \ frameworks/base/core/java/android/os/Bundle.aidl \ frameworks/base/core/java/android/os/DropBoxManager.aidl \ frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \ diff --git a/CleanSpec.mk b/CleanSpec.mk index c7bd9fd..15e073e 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -86,6 +86,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/androi $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/trustedlogic) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/com/trustedlogic) $(call add-clean-step, rm -rf $(OUT_DIR)/target/target/common/obj/APPS/Music2_intermediates) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc/INdefTag.java) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST diff --git a/api/current.xml b/api/current.xml index 57518a7..9ad6a86 100644 --- a/api/current.xml +++ b/api/current.xml @@ -250330,7 +250330,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="arg0" type="T"> +<parameter name="t" type="T"> </parameter> </method> </interface> @@ -250370,6 +250370,16 @@ deprecated="not deprecated" visibility="public" > +<field name="MAXIMUM_PACKED_VALUE" + type="int" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="MAXIMUM_VALUE" type="int" transient="false" @@ -250751,6 +250761,17 @@ visibility="public" > </field> +<field name="OP_CHECK_CAST_JUMBO" + type="int" + transient="false" + volatile="false" + value="511" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_CMPG_DOUBLE" type="int" transient="false" @@ -250850,6 +250871,17 @@ visibility="public" > </field> +<field name="OP_CONST_CLASS_JUMBO" + type="int" + transient="false" + volatile="false" + value="255" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_CONST_HIGH16" type="int" transient="false" @@ -251103,6 +251135,17 @@ visibility="public" > </field> +<field name="OP_FILLED_NEW_ARRAY_JUMBO" + type="int" + transient="false" + volatile="false" + value="1535" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_FILLED_NEW_ARRAY_RANGE" type="int" transient="false" @@ -251345,6 +251388,17 @@ visibility="public" > </field> +<field name="OP_IGET_BOOLEAN_JUMBO" + type="int" + transient="false" + volatile="false" + value="2559" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IGET_BYTE" type="int" transient="false" @@ -251356,6 +251410,17 @@ visibility="public" > </field> +<field name="OP_IGET_BYTE_JUMBO" + type="int" + transient="false" + volatile="false" + value="2815" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IGET_CHAR" type="int" transient="false" @@ -251367,6 +251432,28 @@ visibility="public" > </field> +<field name="OP_IGET_CHAR_JUMBO" + type="int" + transient="false" + volatile="false" + value="3071" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OP_IGET_JUMBO" + type="int" + transient="false" + volatile="false" + value="1791" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IGET_OBJECT" type="int" transient="false" @@ -251378,6 +251465,17 @@ visibility="public" > </field> +<field name="OP_IGET_OBJECT_JUMBO" + type="int" + transient="false" + volatile="false" + value="2303" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IGET_OBJECT_QUICK" type="int" transient="false" @@ -251411,6 +251509,17 @@ visibility="public" > </field> +<field name="OP_IGET_SHORT_JUMBO" + type="int" + transient="false" + volatile="false" + value="3327" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IGET_WIDE" type="int" transient="false" @@ -251422,6 +251531,17 @@ visibility="public" > </field> +<field name="OP_IGET_WIDE_JUMBO" + type="int" + transient="false" + volatile="false" + value="2047" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IGET_WIDE_QUICK" type="int" transient="false" @@ -251455,6 +251575,17 @@ visibility="public" > </field> +<field name="OP_INSTANCE_OF_JUMBO" + type="int" + transient="false" + volatile="false" + value="767" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_INT_TO_BYTE" type="int" transient="false" @@ -251543,6 +251674,17 @@ visibility="public" > </field> +<field name="OP_INVOKE_DIRECT_JUMBO" + type="int" + transient="false" + volatile="false" + value="9471" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_INVOKE_DIRECT_RANGE" type="int" transient="false" @@ -251565,6 +251707,17 @@ visibility="public" > </field> +<field name="OP_INVOKE_INTERFACE_JUMBO" + type="int" + transient="false" + volatile="false" + value="9983" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_INVOKE_INTERFACE_RANGE" type="int" transient="false" @@ -251587,6 +251740,17 @@ visibility="public" > </field> +<field name="OP_INVOKE_STATIC_JUMBO" + type="int" + transient="false" + volatile="false" + value="9727" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_INVOKE_STATIC_RANGE" type="int" transient="false" @@ -251609,6 +251773,17 @@ visibility="public" > </field> +<field name="OP_INVOKE_SUPER_JUMBO" + type="int" + transient="false" + volatile="false" + value="9215" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_INVOKE_SUPER_QUICK" type="int" transient="false" @@ -251653,6 +251828,17 @@ visibility="public" > </field> +<field name="OP_INVOKE_VIRTUAL_JUMBO" + type="int" + transient="false" + volatile="false" + value="8959" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_INVOKE_VIRTUAL_QUICK" type="int" transient="false" @@ -251708,6 +251894,17 @@ visibility="public" > </field> +<field name="OP_IPUT_BOOLEAN_JUMBO" + type="int" + transient="false" + volatile="false" + value="4351" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IPUT_BYTE" type="int" transient="false" @@ -251719,6 +251916,17 @@ visibility="public" > </field> +<field name="OP_IPUT_BYTE_JUMBO" + type="int" + transient="false" + volatile="false" + value="4607" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IPUT_CHAR" type="int" transient="false" @@ -251730,6 +251938,28 @@ visibility="public" > </field> +<field name="OP_IPUT_CHAR_JUMBO" + type="int" + transient="false" + volatile="false" + value="4863" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OP_IPUT_JUMBO" + type="int" + transient="false" + volatile="false" + value="3583" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IPUT_OBJECT" type="int" transient="false" @@ -251741,6 +251971,17 @@ visibility="public" > </field> +<field name="OP_IPUT_OBJECT_JUMBO" + type="int" + transient="false" + volatile="false" + value="4095" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IPUT_OBJECT_QUICK" type="int" transient="false" @@ -251774,6 +252015,17 @@ visibility="public" > </field> +<field name="OP_IPUT_SHORT_JUMBO" + type="int" + transient="false" + volatile="false" + value="5119" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IPUT_WIDE" type="int" transient="false" @@ -251785,6 +252037,17 @@ visibility="public" > </field> +<field name="OP_IPUT_WIDE_JUMBO" + type="int" + transient="false" + volatile="false" + value="3839" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_IPUT_WIDE_QUICK" type="int" transient="false" @@ -252170,6 +252433,17 @@ visibility="public" > </field> +<field name="OP_NEW_ARRAY_JUMBO" + type="int" + transient="false" + volatile="false" + value="1279" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_NEW_INSTANCE" type="int" transient="false" @@ -252181,6 +252455,17 @@ visibility="public" > </field> +<field name="OP_NEW_INSTANCE_JUMBO" + type="int" + transient="false" + volatile="false" + value="1023" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_NOP" type="int" transient="false" @@ -252489,6 +252774,17 @@ visibility="public" > </field> +<field name="OP_SGET_BOOLEAN_JUMBO" + type="int" + transient="false" + volatile="false" + value="6143" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SGET_BYTE" type="int" transient="false" @@ -252500,6 +252796,17 @@ visibility="public" > </field> +<field name="OP_SGET_BYTE_JUMBO" + type="int" + transient="false" + volatile="false" + value="6399" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SGET_CHAR" type="int" transient="false" @@ -252511,6 +252818,28 @@ visibility="public" > </field> +<field name="OP_SGET_CHAR_JUMBO" + type="int" + transient="false" + volatile="false" + value="6655" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OP_SGET_JUMBO" + type="int" + transient="false" + volatile="false" + value="5375" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SGET_OBJECT" type="int" transient="false" @@ -252522,6 +252851,17 @@ visibility="public" > </field> +<field name="OP_SGET_OBJECT_JUMBO" + type="int" + transient="false" + volatile="false" + value="5887" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SGET_SHORT" type="int" transient="false" @@ -252533,6 +252873,17 @@ visibility="public" > </field> +<field name="OP_SGET_SHORT_JUMBO" + type="int" + transient="false" + volatile="false" + value="6911" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SGET_WIDE" type="int" transient="false" @@ -252544,6 +252895,17 @@ visibility="public" > </field> +<field name="OP_SGET_WIDE_JUMBO" + type="int" + transient="false" + volatile="false" + value="5631" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SGET_WIDE_VOLATILE" type="int" transient="false" @@ -252698,6 +253060,17 @@ visibility="public" > </field> +<field name="OP_SPUT_BOOLEAN_JUMBO" + type="int" + transient="false" + volatile="false" + value="7935" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SPUT_BYTE" type="int" transient="false" @@ -252709,6 +253082,17 @@ visibility="public" > </field> +<field name="OP_SPUT_BYTE_JUMBO" + type="int" + transient="false" + volatile="false" + value="8191" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SPUT_CHAR" type="int" transient="false" @@ -252720,6 +253104,28 @@ visibility="public" > </field> +<field name="OP_SPUT_CHAR_JUMBO" + type="int" + transient="false" + volatile="false" + value="8447" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="OP_SPUT_JUMBO" + type="int" + transient="false" + volatile="false" + value="7167" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SPUT_OBJECT" type="int" transient="false" @@ -252731,6 +253137,17 @@ visibility="public" > </field> +<field name="OP_SPUT_OBJECT_JUMBO" + type="int" + transient="false" + volatile="false" + value="7679" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SPUT_SHORT" type="int" transient="false" @@ -252742,6 +253159,17 @@ visibility="public" > </field> +<field name="OP_SPUT_SHORT_JUMBO" + type="int" + transient="false" + volatile="false" + value="8703" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SPUT_WIDE" type="int" transient="false" @@ -252753,6 +253181,17 @@ visibility="public" > </field> +<field name="OP_SPUT_WIDE_JUMBO" + type="int" + transient="false" + volatile="false" + value="7423" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="OP_SPUT_WIDE_VOLATILE" type="int" transient="false" @@ -367094,9 +367533,9 @@ > <parameter name="buf" type="byte[]"> </parameter> -<parameter name="off" type="int"> +<parameter name="offset" type="int"> </parameter> -<parameter name="nbytes" type="int"> +<parameter name="byteCount" type="int"> </parameter> </method> </class> @@ -367178,9 +367617,9 @@ > <parameter name="buf" type="byte[]"> </parameter> -<parameter name="off" type="int"> +<parameter name="offset" type="int"> </parameter> -<parameter name="nbytes" type="int"> +<parameter name="byteCount" type="int"> </parameter> </method> </class> @@ -367398,9 +367837,9 @@ > <parameter name="buf" type="byte[]"> </parameter> -<parameter name="off" type="int"> +<parameter name="offset" type="int"> </parameter> -<parameter name="nbytes" type="int"> +<parameter name="byteCount" type="int"> </parameter> </method> <method name="end" @@ -367523,7 +367962,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buf" type="byte[]"> +<parameter name="dictionary" type="byte[]"> </parameter> </method> <method name="setDictionary" @@ -367538,9 +367977,9 @@ > <parameter name="buf" type="byte[]"> </parameter> -<parameter name="off" type="int"> +<parameter name="offset" type="int"> </parameter> -<parameter name="nbytes" type="int"> +<parameter name="byteCount" type="int"> </parameter> </method> <method name="setInput" @@ -367568,9 +368007,9 @@ > <parameter name="buf" type="byte[]"> </parameter> -<parameter name="off" type="int"> +<parameter name="offset" type="int"> </parameter> -<parameter name="nbytes" type="int"> +<parameter name="byteCount" type="int"> </parameter> </method> <method name="setLevel" @@ -368098,9 +368537,9 @@ > <parameter name="buf" type="byte[]"> </parameter> -<parameter name="off" type="int"> +<parameter name="offset" type="int"> </parameter> -<parameter name="nbytes" type="int"> +<parameter name="byteCount" type="int"> </parameter> <exception name="DataFormatException" type="java.util.zip.DataFormatException"> </exception> @@ -368148,7 +368587,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buf" type="byte[]"> +<parameter name="dictionary" type="byte[]"> </parameter> </method> <method name="setDictionary" @@ -368161,11 +368600,11 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buf" type="byte[]"> +<parameter name="dictionary" type="byte[]"> </parameter> -<parameter name="off" type="int"> +<parameter name="offset" type="int"> </parameter> -<parameter name="nbytes" type="int"> +<parameter name="byteCount" type="int"> </parameter> </method> <method name="setInput" @@ -368193,9 +368632,9 @@ > <parameter name="buf" type="byte[]"> </parameter> -<parameter name="off" type="int"> +<parameter name="offset" type="int"> </parameter> -<parameter name="nbytes" type="int"> +<parameter name="byteCount" type="int"> </parameter> </method> </class> @@ -372711,7 +373150,7 @@ </parameter> <parameter name="offset" type="int"> </parameter> -<parameter name="len" type="int"> +<parameter name="byteCount" type="int"> </parameter> </constructor> <method name="getIV" diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index f5a46c5..a196792 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -16,25 +16,19 @@ package android.app; -import java.text.NumberFormat; -import java.util.Date; +import com.android.internal.R; -import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; -import android.media.AudioManager; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; -import android.text.format.DateFormat; -import android.text.format.DateUtils; -import android.util.Slog; import android.view.View; import android.widget.RemoteViews; -import com.android.internal.R; +import java.text.NumberFormat; /** * A class that represents how a persistent notification is to be presented to @@ -46,8 +40,6 @@ import com.android.internal.R; */ public class Notification implements Parcelable { - private static final String TAG = "Notification"; - /** * Use all default values (where applicable). */ @@ -402,6 +394,7 @@ public class Notification implements Parcelable } } + @Override public Notification clone() { Notification that = new Notification(); @@ -645,7 +638,10 @@ public class Notification implements Parcelable public Builder(Context context) { mContext = context; + + // Set defaults to match the defaults of a Notification mWhen = System.currentTimeMillis(); + mAudioStreamType = STREAM_DEFAULT; } public Builder setWhen(long when) { diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index fa7f794..97e6931 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -61,10 +61,16 @@ public class StatusBarManager { /** * Flag for {@link #disable} to hide only the navigation buttons. Don't use this - * unless you're the setup wizard. + * unless you're a special part of the system UI (i.e., setup wizard, keyguard). */ public static final int DISABLE_NAVIGATION = 0x00000020; + /** + * Flag for {@link #disable} to hide only the clock. You might use this if your activity has + * its own clock making the status bar's clock redundant. + */ + public static final int DISABLE_CLOCK = 0x00000040; + /** * Re-enable all of the status bar features that you've disabled. diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index bae6ad3..4a4edd2 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -1927,9 +1927,13 @@ public class SyncStorageEngine extends Handler { } AuthorityInfo authority = mAuthorities.get(authorityId); if (authority != null) { - Bundle extras = null; + Bundle extras; if (flatExtras != null) { extras = unflattenBundle(flatExtras); + } else { + // if we are unable to parse the extras for whatever reason convert this + // to a regular sync by creating an empty extras + extras = new Bundle(); } PendingOperation op = new PendingOperation( authority.account, syncSource, diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java index 915e342..641a576 100644 --- a/core/java/android/net/http/AndroidHttpClient.java +++ b/core/java/android/net/http/AndroidHttpClient.java @@ -80,6 +80,9 @@ public final class AndroidHttpClient implements HttpClient { // Gzip of data shorter than this probably won't be worthwhile public static long DEFAULT_SYNC_MIN_GZIP_BYTES = 256; + // Default connection and socket timeout of 60 seconds. Tweak to taste. + private static final int SOCKET_OPERATION_TIMEOUT = 60 * 1000; + private static final String TAG = "AndroidHttpClient"; private static String[] textContentTypes = new String[] { @@ -113,9 +116,8 @@ public final class AndroidHttpClient implements HttpClient { // and it's not worth it to pay the penalty of checking every time. HttpConnectionParams.setStaleCheckingEnabled(params, false); - // Default connection and socket timeout of 20 seconds. Tweak to taste. - HttpConnectionParams.setConnectionTimeout(params, 20 * 1000); - HttpConnectionParams.setSoTimeout(params, 20 * 1000); + HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT); + HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT); HttpConnectionParams.setSocketBufferSize(params, 8192); // Don't handle redirects -- return them to the caller. Our code @@ -131,7 +133,8 @@ public final class AndroidHttpClient implements HttpClient { schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", - SSLCertificateSocketFactory.getHttpSocketFactory(30 * 1000, sessionCache), 443)); + SSLCertificateSocketFactory.getHttpSocketFactory( + SOCKET_OPERATION_TIMEOUT, sessionCache), 443)); ClientConnectionManager manager = new ThreadSafeClientConnManager(params, schemeRegistry); diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index cd08e33..a663fb8 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -24,6 +24,7 @@ import android.nfc.ILlcpConnectionlessSocket; import android.nfc.INfcTag; import android.nfc.IP2pTarget; import android.nfc.IP2pInitiator; +import android.nfc.INfcSecureElement; /** * @hide @@ -36,9 +37,12 @@ interface INfcAdapter INfcTag getNfcTagInterface(); IP2pTarget getP2pTargetInterface(); IP2pInitiator getP2pInitiatorInterface(); + INfcSecureElement getNfcSecureElementInterface(); // NfcAdapter-class related methods boolean isEnabled(); + NdefMessage localGet(); + void localSet(in NdefMessage message); void openTagConnection(in Tag tag); // Non-public methods diff --git a/core/java/android/nfc/INdefTag.aidl b/core/java/android/nfc/INfcSecureElement.aidl index d131ebe..aa98dd2 100644..100755 --- a/core/java/android/nfc/INdefTag.aidl +++ b/core/java/android/nfc/INfcSecureElement.aidl @@ -16,13 +16,13 @@ package android.nfc; -import android.nfc.NdefMessage; - /** - * @hide + * {@hide} */ -interface INdefTag -{ - NdefMessage read(int nativeHandle); - boolean write(int nativeHandle, in NdefMessage msg); +interface INfcSecureElement { + int openSecureElementConnection(); + int closeSecureElementConnection(int nativeHandle); + byte[] exchangeAPDU(int nativeHandle, in byte[] data); + int[] getSecureElementTechList(int nativeHandle); + byte[] getSecureElementUid(int nativeHandle); }
\ No newline at end of file diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl index 13b97d6..ad3c1bb 100644 --- a/core/java/android/nfc/INfcTag.aidl +++ b/core/java/android/nfc/INfcTag.aidl @@ -25,7 +25,7 @@ interface INfcTag { int close(int nativeHandle); int connect(int nativeHandle); - String getType(int nativeHandle); + int[] getTechList(int nativeHandle); byte[] getUid(int nativeHandle); boolean isNdef(int nativeHandle); boolean isPresent(int nativeHandle); diff --git a/core/java/android/nfc/NdefTag.java b/core/java/android/nfc/NdefTag.java deleted file mode 100644 index eb9d0dc..0000000 --- a/core/java/android/nfc/NdefTag.java +++ /dev/null @@ -1,245 +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; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Represents a discovered tag that contains {@link NdefMessage}s (or a tag that can store them). - * In practice, a tag is a thing that an NFC-enabled device can communicate with. This - * class is a representation of such a tag and can contain the NDEF messages shared by the tag. - * <p>An NDEF tag can contain zero or more NDEF messages (represented by {@link NdefMessage} - * objects) in addition to the basic tag properties of UID and Type. - * <p> - * {@link NdefTag}s that have been initialized will usually contain a single {@link NdefMessage} - * (and that Message can contain multiple {@link NdefRecord}s). However it - * is possible for {@link NdefTag}s to contain multiple {@link NdefMessage}s. - * <p>{@link NfcAdapter#createNdefTagConnection createNdefTagConnection()} can be used to modify the - * contents of some tags. - * <p>This is an immutable data class. All properties are set at Tag discovery - * 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 NdefTag extends Tag implements Parcelable { - /** - * Target for NFC Forum Type 1 compliant tag. - * <p>This is based on Jewel/Topaz technology - */ - public static final String TARGET_TYPE_1 = "type_1"; - - /** - * Target for NFC Forum Type 2 compliant tag. - * <p>This is based on Mifare Ultralight technology. - */ - public static final String TARGET_TYPE_2 = "type_2"; - - /** - * Target for NFC Forum Type 3 compliant tag. - * <p>This is based on Felica technology. - */ - public static final String TARGET_TYPE_3 = "type_3"; - - /** - * Target for NFC Forum Type 4 compliant tag. - * <p>This is based on Mifare Desfire technology. - */ - public static final String TARGET_TYPE_4 = "type_4"; - - /** - * Target for NFC Forum Enabled: Mifare Classic tag. - * <p>This is not strictly a NFC Forum tag type, but is a common - * NDEF message container. - */ - public static final String TARGET_MIFARE_CLASSIC = "type_mifare_classic"; - - /** - * Any other target. - */ - public static final String TARGET_OTHER = "other"; - - private final String[] mNdefTargets; - private final NdefMessage[][] mMessages; // one NdefMessage[] per NDEF target - private NdefMessage[] mFlatMessages; // collapsed mMessages, built lazily, protected by (this) - - /** - * Hidden constructor to be used by NFC service only. - * @hide - */ - public NdefTag(byte[] id, String[] rawTargets, byte[] pollBytes, byte[] activationBytes, - int serviceHandle, String[] ndefTargets, NdefMessage[][] messages) { - super(id, true, rawTargets, pollBytes, activationBytes, serviceHandle); - if (ndefTargets == null || messages == null) { - throw new IllegalArgumentException("ndefTargets or messages cannot be null"); - } - if (ndefTargets.length != messages.length){ - throw new IllegalArgumentException("ndefTargets and messages arrays must match"); - } - for (NdefMessage[] ms : messages) { - if (ms == null) { - throw new IllegalArgumentException("messages elements cannot be null"); - } - } - mNdefTargets = ndefTargets; - mMessages = messages; - } - - /** - * Construct a mock NdefTag. - * <p>This is an application constructed tag, so NfcAdapter methods on this - * Tag such as {@link NfcAdapter#createRawTagConnection} will 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 rawTargets must not be null - * @param pollBytes can be null - * @param activationBytes can be null - * @param ndefTargets NDEF target array, such as {TARGET_TYPE_2}, cannot be null - * @param messages messages, one array per NDEF target, cannot be null - * @return freshly constructed NdefTag - */ - public static NdefTag createMockNdefTag(byte[] id, String[] rawTargets, byte[] pollBytes, - byte[] activationBytes, String[] ndefTargets, NdefMessage[][] messages) { - // set serviceHandle to 0 to indicate mock tag - return new NdefTag(id, rawTargets, pollBytes, activationBytes, 0, ndefTargets, messages); - } - - /** - * Get all NDEF Messages. - * <p> - * This retrieves the NDEF Messages that were found on the Tag at discovery - * time. It does not cause any further RF activity, and does not block. - * <p> - * Most tags only contain a single NDEF message. - * - * @return NDEF Messages found at Tag discovery - */ - public NdefMessage[] getNdefMessages() { - // common-case optimization - if (mMessages.length == 1) { - return mMessages[0]; - } - - // return cached flat array - synchronized(this) { - if (mFlatMessages != null) { - return mFlatMessages; - } - // not cached - build a flat array - int sz = 0; - for (NdefMessage[] ms : mMessages) { - sz += ms.length; - } - mFlatMessages = new NdefMessage[sz]; - int i = 0; - for (NdefMessage[] ms : mMessages) { - System.arraycopy(ms, 0, mFlatMessages, i, ms.length); - i += ms.length; - } - return mFlatMessages; - } - } - - /** - * Get only the NDEF Messages from a single NDEF target on a tag. - * <p> - * This retrieves the NDEF Messages that were found on the Tag at discovery - * time. It does not cause any further RF activity, and does not block. - * <p> - * Most tags only contain a single NDEF message. - * - * @param target one of targets strings provided by getNdefTargets() - * @return NDEF Messages found at Tag discovery - */ - public NdefMessage[] getNdefMessages(String target) { - for (int i=0; i<mNdefTargets.length; i++) { - if (target.equals(mNdefTargets[i])) { - return mMessages[i]; - } - } - throw new IllegalArgumentException("target (" + target + ") not found"); - } - - /** - * Return the NDEF targets on this Tag that support NDEF messages. - * - * @return - */ - public String[] getNdefTargets() { - return mNdefTargets; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - // Tag fields - dest.writeInt(mIsNdef ? 1 : 0); - writeBytesWithNull(dest, mId); - dest.writeInt(mRawTargets.length); - dest.writeStringArray(mRawTargets); - writeBytesWithNull(dest, mPollBytes); - writeBytesWithNull(dest, mActivationBytes); - dest.writeInt(mServiceHandle); - - // NdefTag fields - dest.writeInt(mNdefTargets.length); - dest.writeStringArray(mNdefTargets); - dest.writeInt(mMessages.length); - for (NdefMessage[] ms : mMessages) { - dest.writeInt(ms.length); - dest.writeTypedArray(ms, flags); - } - } - - public static final Parcelable.Creator<NdefTag> CREATOR = - new Parcelable.Creator<NdefTag>() { - public NdefTag createFromParcel(Parcel in) { - boolean isNdef = (in.readInt() == 1); - if (!isNdef) { - throw new IllegalArgumentException("Creating NdefTag from Tag parcel"); - } - - // Tag fields - byte[] id = readBytesWithNull(in); - String[] rawTargets = new String[in.readInt()]; - in.readStringArray(rawTargets); - byte[] pollBytes = readBytesWithNull(in); - byte[] activationBytes = readBytesWithNull(in); - int serviceHandle = in.readInt(); - - // NdefTag fields - String[] ndefTargets = new String[in.readInt()]; - in.readStringArray(ndefTargets); - NdefMessage[][] messages = new NdefMessage[in.readInt()][]; - for (int i=0; i<messages.length; i++) { - messages[i] = new NdefMessage[in.readInt()]; - in.readTypedArray(messages[i], NdefMessage.CREATOR); - } - return new NdefTag(id, rawTargets, pollBytes, activationBytes, serviceHandle, - ndefTargets, messages); - } - public NdefTag[] newArray(int size) { - return new NdefTag[size]; - } - }; -}
\ No newline at end of file diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 88b6ea4..a1c22bf 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -1,25 +1,26 @@ /* - * 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. + * 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; -import java.lang.UnsupportedOperationException; - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.ActivityThread; -import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.nfc.INfcAdapter; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -40,6 +41,12 @@ public final class NfcAdapter { public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; /** + * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED + * @hide + */ + public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST"; + + /** * Mandatory Tag extra for the ACTION_TAG intents. * @hide */ @@ -170,6 +177,14 @@ public final class NfcAdapter { } /** + * Returns the binder interface to the service. + * @hide + */ + public INfcAdapter getService() { + return mService; + } + + /** * Helper to check if this device has FEATURE_NFC, but without using * a context. * Equivalent to @@ -230,8 +245,11 @@ public final class NfcAdapter { } } - /** NFC service dead - attempt best effort recovery */ - /*package*/ void attemptDeadServiceRecovery(Exception e) { + /** + * NFC service dead - attempt best effort recovery + * @hide + */ + public void attemptDeadServiceRecovery(Exception e) { Log.e(TAG, "NFC service dead - attempting to recover", e); INfcAdapter service = getServiceInterface(); if (service == null) { @@ -301,50 +319,41 @@ public final class NfcAdapter { } /** - * Create a raw tag connection to the default Target - * <p>Requires {@link android.Manifest.permission#NFC} permission. - * @hide - */ - public RawTagConnection createRawTagConnection(Tag tag) { - if (tag.mServiceHandle == 0) { - throw new IllegalArgumentException("mock tag cannot be used for connections"); - } - try { - return new RawTagConnection(this, tag); - } catch (RemoteException e) { - attemptDeadServiceRecovery(e); - return null; - } - } - - /** - * Create a raw tag connection to the specified Target + * Set the NDEF Message that this NFC adapter should appear as to Tag + * readers. + * <p> + * Any Tag reader can read the contents of the local tag when it is in + * proximity, without any further user confirmation. + * <p> + * The implementation of this method must either + * <ul> + * <li>act as a passive tag containing this NDEF message + * <li>provide the NDEF message on over LLCP to peer NFC adapters + * </ul> + * The NDEF message is preserved across reboot. * <p>Requires {@link android.Manifest.permission#NFC} permission. + * + * @param message NDEF message to make public * @hide */ - public RawTagConnection createRawTagConnection(Tag tag, String target) { - if (tag.mServiceHandle == 0) { - throw new IllegalArgumentException("mock tag cannot be used for connections"); - } + public void setLocalNdefMessage(NdefMessage message) { try { - return new RawTagConnection(this, tag, target); + mService.localSet(message); } catch (RemoteException e) { attemptDeadServiceRecovery(e); - return null; } } /** - * Create an NDEF tag connection to the default Target + * Get the NDEF Message that this adapter appears as to Tag readers. * <p>Requires {@link android.Manifest.permission#NFC} permission. + * + * @return NDEF Message that is publicly readable * @hide */ - public NdefTagConnection createNdefTagConnection(NdefTag tag) { - if (tag.mServiceHandle == 0) { - throw new IllegalArgumentException("mock tag cannot be used for connections"); - } + public NdefMessage getLocalNdefMessage() { try { - return new NdefTagConnection(this, tag); + return mService.localGet(); } catch (RemoteException e) { attemptDeadServiceRecovery(e); return null; @@ -352,18 +361,14 @@ public final class NfcAdapter { } /** - * Create an NDEF tag connection to the specified Target - * <p>Requires {@link android.Manifest.permission#NFC} permission. + * Create an Nfc Secure Element Connection * @hide */ - public NdefTagConnection createNdefTagConnection(NdefTag tag, String target) { - if (tag.mServiceHandle == 0) { - throw new IllegalArgumentException("mock tag cannot be used for connections"); - } + public NfcSecureElement createNfcSecureElementConnection() { try { - return new NdefTagConnection(this, tag, target); + return new NfcSecureElement(mService.getNfcSecureElementInterface()); } catch (RemoteException e) { - attemptDeadServiceRecovery(e); + Log.e(TAG, "createNfcSecureElementConnection failed", e); return null; } } diff --git a/core/java/android/nfc/NfcSecureElement.java b/core/java/android/nfc/NfcSecureElement.java new file mode 100755 index 0000000..5f4c066 --- /dev/null +++ b/core/java/android/nfc/NfcSecureElement.java @@ -0,0 +1,138 @@ +/* + * 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; + +import android.nfc.technology.TagTechnology; +import android.os.RemoteException; +import android.util.Log; + +import java.io.IOException; + +//import android.util.Log; + +/** + * This class provides the primary API for managing all aspects Secure Element. + * Get an instance of this class by calling + * Context.getSystemService(Context.NFC_SERVICE). + * @hide + */ +public final class NfcSecureElement { + + private static final String TAG = "NfcSecureElement"; + + private INfcSecureElement mService; + + + /** + * @hide + */ + public NfcSecureElement(INfcSecureElement mSecureElementService) { + mService = mSecureElementService; + } + + public int openSecureElementConnection(String seType) throws IOException { + if (seType.equals("SmartMX")) { + try { + int handle = mService.openSecureElementConnection(); + // Handle potential errors + if (handle != 0) { + return handle; + } else { + throw new IOException("SmartMX connection not allowed"); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in openSecureElementConnection(): ", e); + return 0; + } + + } else if (seType.equals("UICC")) { + return 0; + } else { + throw new IOException("Wrong Secure Element type"); + } + } + + + public byte [] exchangeAPDU(int handle,byte [] data) throws IOException { + + + // Perform exchange APDU + try { + byte[] response = mService.exchangeAPDU(handle, data); + // Handle potential errors + if (response == null) { + throw new IOException("Exchange APDU failed"); + } + return response; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in exchangeAPDU(): ", e); + return null; + } + } + + public void closeSecureElementConnection(int handle) throws IOException { + + try { + int status = mService.closeSecureElementConnection(handle); + // Handle potential errors + if (ErrorCodes.isError(status)) { + throw new IOException("Error during the conection close"); + }; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in closeSecureElement(): ", e); + } + } + + + /** + * Returns target type. constants. + * + * @return Secure Element technology type. The possible values are defined in + * {@link TagTechnology} + * + */ + public int[] getSecureElementTechList(int handle) throws IOException { + try { + return mService.getSecureElementTechList(handle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getType(): ", e); + return null; + } + } + + /** + * Returns Secure Element UID. + * + * @return Secure Element UID. + */ + public byte[] getSecureElementUid(int handle) throws IOException { + + byte[] uid = null; + try { + uid = mService.getSecureElementUid(handle); + // Handle potential errors + if (uid == null) { + throw new IOException("Get Secure Element UID failed"); + } + return uid; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getType(): ", e); + return null; + } + } + +} diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java index 5d0b04c..04304dd 100644 --- a/core/java/android/nfc/Tag.java +++ b/core/java/android/nfc/Tag.java @@ -16,8 +16,21 @@ 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.NfcA; +import android.nfc.technology.NfcB; +import android.nfc.technology.NfcF; +import android.nfc.technology.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. @@ -30,13 +43,13 @@ import android.os.Parcelable; * {@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 RawTagConnection} - * (with {@link NfcAdapter#createRawTagConnection createRawTagConnection()}). + * directly queried for its UID and Type, or used to create a {@link TagTechnology} + * (with {@link Tag#getTechnology(int)}). * <p> - * A {@link Tag} can be used to create a {@link RawTagConnection} only while the tag is in + * 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 * {@link Tag} object (in {@link NfcAdapter#ACTION_TAG_DISCOVERED}) should be used to create a - * {@link RawTagConnection}. + * {@link TagTechnology}. * <p>This is an immutable data class. All properties are set at Tag discovery * 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 @@ -44,78 +57,39 @@ import android.os.Parcelable; * @hide */ public class Tag implements Parcelable { - /** - * ISO 14443-3A technology. - * <p> - * Includes Topaz (which is -3A compatible) - */ - public static final String TARGET_ISO_14443_3A = "iso14443_3a"; - - /** - * ISO 14443-3B technology. - */ - public static final String TARGET_ISO_14443_3B = "iso14443_3b"; - - /** - * ISO 14443-4 technology. - */ - public static final String TARGET_ISO_14443_4 = "iso14443_4"; - - /** - * ISO 15693 technology, commonly known as RFID. - */ - public static final String TARGET_ISO_15693 = "iso15693"; - - /** - * JIS X-6319-4 technology, commonly known as Felica. - */ - public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4"; - - /** - * Any other technology. - */ - public static final String TARGET_OTHER = "other"; - - /*package*/ final boolean mIsNdef; /*package*/ final byte[] mId; - /*package*/ final String[] mRawTargets; - /*package*/ final byte[] mPollBytes; - /*package*/ final byte[] mActivationBytes; + /*package*/ final int[] mTechList; + /*package*/ final Bundle[] mTechExtras; /*package*/ final int mServiceHandle; // for use by NFC service, 0 indicates a mock /** * Hidden constructor to be used by NFC service and internal classes. * @hide */ - public Tag(byte[] id, boolean isNdef, String[] rawTargets, byte[] pollBytes, - byte[] activationBytes, int serviceHandle) { - if (rawTargets == null) { + public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle) { + if (techList == null) { throw new IllegalArgumentException("rawTargets cannot be null"); } - mIsNdef = isNdef; mId = id; - mRawTargets = rawTargets; - mPollBytes = pollBytes; - mActivationBytes = activationBytes; + mTechList = Arrays.copyOf(techList, techList.length); + // Ensure mTechExtras is as long as mTechList + mTechExtras = Arrays.copyOf(techListExtras, techList.length); mServiceHandle = serviceHandle; } /** * Construct a mock Tag. * <p>This is an application constructed tag, so NfcAdapter methods on this - * Tag such as {@link NfcAdapter#createRawTagConnection} will fail with + * Tag such as {@link #getTechnology} 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 rawTargets must not be null - * @param pollBytes can be null - * @param activationBytes can be null + * @param techList must not be null * @return freshly constructed tag */ - public static Tag createMockTag(byte[] id, String[] rawTargets, byte[] pollBytes, - byte[] activationBytes) { + public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) { // set serviceHandle to 0 to indicate mock tag - return new Tag(id, false, rawTargets, pollBytes, activationBytes, 0); + return new Tag(id, techList, techListExtras, 0); } /** @@ -127,16 +101,6 @@ public class Tag implements Parcelable { } /** - * Return the available targets that this NFC adapter can use to create - * a RawTagConnection. - * - * @return raw targets, will not be null - */ - public String[] getRawTargets() { - return mRawTargets; - } - - /** * Get the Tag Identifier (if it has one). * <p>Tag ID is usually a serial number for the tag. * @@ -147,37 +111,72 @@ public class Tag implements Parcelable { } /** - * Get the low-level bytes returned by this Tag at poll-time. - * <p>These can be used to help with advanced identification of a Tag. - * <p>The meaning of these bytes depends on the Tag technology. - * <p>ISO14443-3A: ATQA/SENS_RES - * <p>ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES - * <p>JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte) - * <p>ISO15693: response flags (1 byte), DSFID (1 byte) - * from SENSF_RES + * Returns technologies present in the tag that this implementation understands, + * or a zero length array if there are no supported technologies on this tag. * - * @return poll bytes, or null if they do not exist for this Tag technology - * @hide + * The elements of the list are guaranteed be one of the constants defined in + * {@link TagTechnology}. + * + * The ordering of the returned array is undefined and should not be relied upon. */ - public byte[] getPollBytes() { - return mPollBytes; + public int[] getTechnologyList() { + return Arrays.copyOf(mTechList, mTechList.length); } /** - * Get the low-level bytes returned by this Tag at activation-time. - * <p>These can be used to help with advanced identification of a Tag. - * <p>The meaning of these bytes depends on the Tag technology. - * <p>ISO14443-3A: SAK/SEL_RES - * <p>ISO14443-3B: null - * <p>ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS <TODO: confirm> - * <p>ISO14443-3B & ISO14443-4: ATTRIB response - * <p>JIS_X_6319_4: null - * <p>ISO15693: response flags (1 byte), DSFID (1 byte): null - * @return activation bytes, or null if they do not exist for this Tag technology - * @hide + * Returns the technology, or null if not present */ - public byte[] getActivationBytes() { - return mActivationBytes; + public TagTechnology getTechnology(int tech) { + int pos = -1; + for (int idx = 0; idx < mTechList.length; idx++) { + if (mTechList[idx] == tech) { + pos = idx; + break; + } + } + if (pos < 0) { + return null; + } + + Bundle extras = mTechExtras[pos]; + NfcAdapter adapter = NfcAdapter.getDefaultAdapter(); + 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.TYPE_1: + case TagTechnology.TYPE_2: + case TagTechnology.TYPE_3: + case TagTechnology.TYPE_4: { + return new Ndef(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); + } + + default: { + throw new UnsupportedOperationException("Tech " + tech + " not supported"); + } + } + } catch (RemoteException e) { + return null; + } } @Override @@ -185,13 +184,9 @@ public class Tag implements Parcelable { StringBuilder sb = new StringBuilder("TAG ") .append("uid = ") .append(mId) - .append(" poll ") - .append(mPollBytes) - .append(" activation ") - .append(mActivationBytes) - .append(" Raw ["); - for (String s : mRawTargets) { - sb.append(s) + .append(" Tech ["); + for (int i : mTechList) { + sb.append(i) .append(", "); } return sb.toString(); @@ -221,37 +216,32 @@ public class Tag implements Parcelable { return 0; } - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mIsNdef ? 1 : 0); writeBytesWithNull(dest, mId); - dest.writeInt(mRawTargets.length); - dest.writeStringArray(mRawTargets); - writeBytesWithNull(dest, mPollBytes); - writeBytesWithNull(dest, mActivationBytes); + dest.writeInt(mTechList.length); + dest.writeIntArray(mTechList); + dest.writeTypedArray(mTechExtras, 0); dest.writeInt(mServiceHandle); } public static final Parcelable.Creator<Tag> CREATOR = new Parcelable.Creator<Tag>() { + @Override public Tag createFromParcel(Parcel in) { - boolean isNdef = (in.readInt() == 1); - if (isNdef) { - throw new IllegalArgumentException("Creating Tag from NdefTag parcel"); - } // Tag fields byte[] id = Tag.readBytesWithNull(in); - String[] rawTargets = new String[in.readInt()]; - in.readStringArray(rawTargets); - byte[] pollBytes = Tag.readBytesWithNull(in); - byte[] activationBytes = Tag.readBytesWithNull(in); + int[] techList = new int[in.readInt()]; + in.readIntArray(techList); + Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR); int serviceHandle = in.readInt(); - return new Tag(id, isNdef, rawTargets, pollBytes, activationBytes, serviceHandle); + return new Tag(id, techList, techExtras, serviceHandle); } + + @Override public Tag[] newArray(int size) { return new Tag[size]; } }; -}
\ No newline at end of file +} diff --git a/core/java/android/nfc/RawTagConnection.java b/core/java/android/nfc/technology/BasicTagTechnology.java index bfdaa77..6b281b9 100644 --- a/core/java/android/nfc/RawTagConnection.java +++ b/core/java/android/nfc/technology/BasicTagTechnology.java @@ -14,31 +14,25 @@ * limitations under the License. */ -package android.nfc; +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.os.RemoteException; import android.util.Log; /** - * A low-level connection to a {@link Tag} target. - * <p>You can acquire this kind of connection with {@link NfcAdapter#createRawTagConnection - * createRawTagConnection()}. Use the connection 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. - * @hide + * A base class for tag technologies that are built on top of transceive(). */ -public class RawTagConnection { +/* package */ abstract class BasicTagTechnology implements TagTechnology { /*package*/ final Tag mTag; /*package*/ boolean mIsConnected; - /*package*/ String mSelectedTarget; + /*package*/ int mSelectedTechnology; private final NfcAdapter mAdapter; // Following fields are final after construction, except for @@ -49,30 +43,40 @@ public class RawTagConnection { private static final String TAG = "NFC"; - /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag, String target) throws RemoteException { - String[] targets = tag.getRawTargets(); + /** + * @hide + */ + public BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException { + int[] techList = tag.getTechnologyList(); int i; // Check target validity - for (i=0;i<targets.length;i++) { - if (target.equals(targets[i])) { + for (i = 0; i < techList.length; i++) { + if (tech == techList[i]) { break; } } - if (i >= targets.length) { - // Target not found - throw new IllegalArgumentException(); + if (i >= techList.length) { + // Technology not found + throw new IllegalArgumentException("Technology " + tech + " not present on tag " + tag); } mAdapter = adapter; - mService = mAdapter.mService; - mTagService = mService.getNfcTagInterface(); + mService = mAdapter.getService(); + try { + mTagService = mService.getNfcTagInterface(); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } mTag = tag; - mSelectedTarget = target; + mSelectedTechnology = tech; } - /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag) throws RemoteException { - this(adapter, tag, tag.getRawTargets()[0]); + /** + * @hide + */ + public BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException { + this(adapter, tag, tag.getTechnologyList()[0]); } /** NFC service dead - attempt best effort recovery */ @@ -80,7 +84,7 @@ public class RawTagConnection { 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.mService; + mService = mAdapter.getService(); try { mTagService = mService.getNfcTagInterface(); } catch (RemoteException e2) { @@ -92,6 +96,7 @@ public class RawTagConnection { * Get the {@link Tag} this connection is associated with. * <p>Requires {@link android.Manifest.permission#NFC} permission. */ + @Override public Tag getTag() { return mTag; } @@ -99,8 +104,9 @@ public class RawTagConnection { /** * <p>Requires {@link android.Manifest.permission#NFC} permission. */ - public String getTagTarget() { - return mSelectedTarget; + @Override + public int getTechnologyId() { + return mSelectedTechnology; } /** @@ -119,7 +125,7 @@ public class RawTagConnection { } try { - return mTagService.isPresent(mTag.mServiceHandle); + return mTagService.isPresent(mTag.getServiceHandle()); } catch (RemoteException e) { attemptDeadServiceRecovery(e); return false; @@ -136,6 +142,7 @@ public class RawTagConnection { * <p>Requires {@link android.Manifest.permission#NFC} permission. * @throws IOException if the target is lost, or connect canceled */ + @Override public void connect() throws IOException { //TODO(nxp): enforce exclusivity mIsConnected = true; @@ -151,10 +158,11 @@ public class RawTagConnection { * calls to {@link #transceive transceive()} or {@link #connect} will fail. * <p>Requires {@link android.Manifest.permission#NFC} permission. */ + @Override public void close() { mIsConnected = false; try { - mTagService.close(mTag.mServiceHandle); + mTagService.close(mTag.getServiceHandle()); } catch (RemoteException e) { attemptDeadServiceRecovery(e); } @@ -173,7 +181,7 @@ public class RawTagConnection { */ public byte[] transceive(byte[] data) throws IOException { try { - byte[] response = mTagService.transceive(mTag.mServiceHandle, data); + byte[] response = mTagService.transceive(mTag.getServiceHandle(), data); if (response == null) { throw new IOException("transcieve failed"); } diff --git a/core/java/android/nfc/technology/IsoDep.java b/core/java/android/nfc/technology/IsoDep.java new file mode 100644 index 0000000..5346c67 --- /dev/null +++ b/core/java/android/nfc/technology/IsoDep.java @@ -0,0 +1,80 @@ +/* + * 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_ATTRIB = "attrib"; + /** @hide */ + public static final String EXTRA_HIST_BYTES = "histbytes"; + + private byte[] mAttrib = null; + private byte[] mHistBytes = null; + + public IsoDep(NfcAdapter adapter, Tag tag, Bundle extras) + throws RemoteException { + super(adapter, tag, TagTechnology.ISO_DEP); + if (extras != null) { + mAttrib = extras.getByteArray(EXTRA_ATTRIB); + mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES); + } + } + + /** + * 3A only + */ + public byte[] getHistoricalBytes() { return mHistBytes; } + + /** + * 3B only + */ + public byte[] getAttrib() { return mAttrib; } + + /** + * Attempts to select the given application on the tag. Note that this only works + * if the tag supports ISO7816-4, which not all IsoDep tags support. If the tag doesn't + * support ISO7816-4 this will throw {@link UnsupportedOperationException}. + * + * This method requires that you call {@link #connect} before calling it. + * + * @throws IOException, UnsupportedOperationException + */ + public void selectAid(byte[] aid) throws IOException, UnsupportedOperationException { + throw new UnsupportedOperationException(); + } +} diff --git a/core/java/android/nfc/technology/MifareClassic.java b/core/java/android/nfc/technology/MifareClassic.java new file mode 100644 index 0000000..c25b71f --- /dev/null +++ b/core/java/android/nfc/technology/MifareClassic.java @@ -0,0 +1,291 @@ +/* + * 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 factory MIFARE read key. + * Use this key to effectively make the payload in this sector + * public. + */ + public static final byte[] DEFAULT_KEY_FACTORY = + {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF}; + public static final byte[] DEFAULT_KEY_ZERO = + {(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00}; + /** + * The well-known, default Mifare Application Directory read key. + */ + public static final byte[] DEFAULT_KEY_MAD = + {(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[] DEFAULT_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(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, not MIFARE + 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 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 sector. + */ + public boolean authenticateSector(int sector, byte[] key, boolean keyA) { + 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] = firstBlockInSector(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) != null)) { + return true; + } + } catch (IOException e) { + // No need to deal with, will return false anyway + } + return false; + } + + /** + * 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 { + byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff); + byte[] blockread_cmd = { 0x30, addr }; // phHal_eMifareRead + + // TODO deal with authentication problems + return transceive(blockread_cmd); + } + +// public byte[] readSector(int sector); + //TODO: define an enumeration for access control settings +// public int readSectorAccessControl(int sector); + + /** + * @throws IOException + * @throws NotAuthenticatedException + */ +/* + public void writeBlock(int block, byte[] data); + public void writeSector(int block, byte[] sector); + public void writeSectorAccessControl(int sector, int access); + public void increment(int block); + public void decrement(int block); +*/ +} diff --git a/core/java/android/nfc/technology/MifareUltralight.java b/core/java/android/nfc/technology/MifareUltralight.java new file mode 100644 index 0000000..dd1dae9 --- /dev/null +++ b/core/java/android/nfc/technology/MifareUltralight.java @@ -0,0 +1,81 @@ +/* + * 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_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(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 { + byte[] blockread_cmd = { 0x30, (byte)block }; // phHal_eMifareRead + return transceive(blockread_cmd); + } + + /** + * @throws IOException + */ +/* + public byte[] readOTP(); + public void writePage(int block, byte[] data); + public void writeBlock(int block, byte[] data); +*/ +} diff --git a/core/java/android/nfc/NdefTagConnection.java b/core/java/android/nfc/technology/Ndef.java index aafdbfd..22460cf 100644 --- a/core/java/android/nfc/NdefTagConnection.java +++ b/core/java/android/nfc/technology/Ndef.java @@ -14,115 +14,122 @@ * limitations under the License. */ -package android.nfc; - -import java.io.IOException; +package android.nfc.technology; +import android.nfc.ErrorCodes; +import android.nfc.FormatException; +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 connection to an NDEF target on an {@link NdefTag}. - * <p>You can acquire this kind of connection with {@link NfcAdapter#createNdefTagConnection - * createNdefTagConnection()}. Use the connection to read or write {@link NdefMessage}s. + * 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()} + * + * <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}. + * * <p class="note"><strong>Note:</strong> * Use of this class requires the {@link android.Manifest.permission#NFC} * permission. - * @hide */ -public class NdefTagConnection extends RawTagConnection { +public final class Ndef extends BasicTagTechnology { public static final int NDEF_MODE_READ_ONCE = 1; public static final int NDEF_MODE_READ_ONLY = 2; public static final int NDEF_MODE_WRITE_ONCE = 3; public static final int NDEF_MODE_WRITE_MANY = 4; public static final int NDEF_MODE_UNKNOWN = 5; - private static final String TAG = "NFC"; - /** * Internal constructor, to be used by NfcAdapter * @hide */ - /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag, String target) throws RemoteException { - super(adapter, tag); - String[] targets = tag.getNdefTargets(); - int i; + public Ndef(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException { + super(adapter, tag, tech); + } - // Check target validity - for (i=0; i<targets.length; i++) { - if (target.equals(targets[i])) { - break; + /** + * Get the primary NDEF message on this tag. This data is read at discovery time + * and does not require a connection. + */ + public NdefMessage getNdefMessage() throws IOException, FormatException { + try { + int serviceHandle = mTag.getServiceHandle(); + NdefMessage msg = mTagService.read(serviceHandle); + if (msg == null) { + int errorCode = mTagService.getLastError(serviceHandle); + switch (errorCode) { + case ErrorCodes.ERROR_IO: + throw new IOException(); + case ErrorCodes.ERROR_INVALID_PARAM: + throw new FormatException(); + default: + // Should not happen + throw new IOException(); + } } - } - if (i >= targets.length) { - // Target not found - throw new IllegalArgumentException(); + return msg; + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + return null; } } /** - * Internal constructor, to be used by NfcAdapter - * @hide + * Get optional extra NDEF messages. + * Some tags may contain extra NDEF messages, but not all + * implementations will be able to read them. */ - /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag) throws RemoteException { - this(adapter, tag, tag.getNdefTargets()[0]); + public NdefMessage[] getExtraNdefMessage() throws IOException, FormatException { + throw new UnsupportedOperationException(); } /** - * Read NDEF message(s). - * This will always return the most up to date payload, and can block. - * It can be canceled with {@link RawTagConnection#close}. - * Most NDEF tags will contain just one NDEF message. + * Get maximum NDEF message size in bytes + */ + public int getSize() { + throw new UnsupportedOperationException(); + } + + /** + * Read/Write mode hint. + * Provides a hint if further reads or writes are likely to succeed. * <p>Requires {@link android.Manifest.permission#NFC} permission. - * @throws FormatException if the tag is not NDEF formatted + * @return one of NDEF_MODE * @throws IOException if the target is lost or connection closed - * @throws FormatException */ - public NdefMessage[] readNdefMessages() throws IOException, FormatException { - //TODO(nxp): do not use getLastError(), it is racy + public int getModeHint() throws IOException { try { - NdefMessage[] msgArray = new NdefMessage[1]; - NdefMessage msg = mTagService.read(mTag.mServiceHandle); - if (msg == null) { - int errorCode = mTagService.getLastError(mTag.mServiceHandle); - switch (errorCode) { + int result = mTagService.getModeHint(mTag.getServiceHandle()); + if (ErrorCodes.isError(result)) { + switch (result) { case ErrorCodes.ERROR_IO: throw new IOException(); - case ErrorCodes.ERROR_INVALID_PARAM: - throw new FormatException(); default: // Should not happen throw new IOException(); } } - msgArray[0] = msg; - return msgArray; + return result; + } catch (RemoteException e) { attemptDeadServiceRecovery(e); - return null; + return NDEF_MODE_UNKNOWN; } } + // Methods that require connect() /** - * Attempt to write an NDEF message to a tag. - * This method will block until the data is written. It can be canceled - * with {@link RawTagConnection#close}. - * Many tags are write-once, so use this method carefully. - * Specification allows for multiple NDEF messages per NDEF tag, but it is - * encourage to only write one message, this so API only takes a single - * message. Use {@link NdefRecord} to write several records to a single tag. - * For write-many tags, use {@link #makeReadOnly} after this method to attempt - * to prevent further modification. For write-once tags this is not - * necessary. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - * - * @throws FormatException if the tag is not suitable for NDEF messages - * @throws IOException if the target is lost or connection closed or the - * write failed + * Overwrite the primary NDEF message + * @throws IOException */ - public void writeNdefMessage(NdefMessage message) throws IOException, FormatException { + public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException { try { - int errorCode = mTagService.write(mTag.mServiceHandle, message); + int errorCode = mTagService.write(mTag.getServiceHandle(), msg); switch (errorCode) { case ErrorCodes.SUCCESS: break; @@ -140,16 +147,26 @@ public class NdefTagConnection extends RawTagConnection { } /** - * Attempts to make the NDEF data in this tag read-only. - * This method will block until the action is complete. It can be canceled - * with {@link RawTagConnection#close}. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - * @return true if the tag is now read-only - * @throws IOException if the target is lost, or connection closed + * 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 + */ + public void writeExtraNdefMessage(int i, NdefMessage msg) throws IOException, FormatException { + throw new UnsupportedOperationException(); + } + + /** + * Set the CC field to indicate this tag is read-only + * @throws IOException */ - public boolean makeReadOnly() throws IOException { + public boolean makeReadonly() throws IOException { try { - int errorCode = mTagService.makeReadOnly(mTag.mServiceHandle); + int errorCode = mTagService.makeReadOnly(mTag.getServiceHandle()); switch (errorCode) { case ErrorCodes.SUCCESS: return true; @@ -168,29 +185,11 @@ public class NdefTagConnection extends RawTagConnection { } /** - * Read/Write mode hint. - * Provides a hint if further reads or writes are likely to succeed. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - * @return one of NDEF_MODE - * @throws IOException if the target is lost or connection closed + * Attempt to use tag specific technology to really make + * the tag read-only + * For NFC Forum Type 1 and 2 only. */ - public int getModeHint() throws IOException { - try { - int result = mTagService.getModeHint(mTag.mServiceHandle); - if (ErrorCodes.isError(result)) { - switch (result) { - case ErrorCodes.ERROR_IO: - throw new IOException(); - default: - // Should not happen - throw new IOException(); - } - } - return result; - - } catch (RemoteException e) { - attemptDeadServiceRecovery(e); - return NDEF_MODE_UNKNOWN; - } + public void makeLowLevelReadonly() { + throw new UnsupportedOperationException(); } -}
\ No newline at end of file +} diff --git a/core/java/android/nfc/technology/NfcA.java b/core/java/android/nfc/technology/NfcA.java new file mode 100644 index 0000000..ef46762 --- /dev/null +++ b/core/java/android/nfc/technology/NfcA.java @@ -0,0 +1,66 @@ +/* + * 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/NfcB.java b/core/java/android/nfc/technology/NfcB.java new file mode 100644 index 0000000..64cb08a --- /dev/null +++ b/core/java/android/nfc/technology/NfcB.java @@ -0,0 +1,55 @@ +/* + * 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-B technology, also known as + * ISO1443-3B. + * + * <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 NfcB extends BasicTagTechnology { + /** @hide */ + public static final String EXTRA_ATQB = "atqb"; + + private byte[] mAtqb; + + public NfcB(NfcAdapter adapter, Tag tag, Bundle extras) + throws RemoteException { + super(adapter, tag, TagTechnology.NFC_B); + } + + /** + * Returns the ATQB/SENSB_RES bytes discovered at tag discovery. + */ + public byte[] getAtqb() { + return mAtqb; + } +} diff --git a/core/java/android/nfc/technology/NfcF.java b/core/java/android/nfc/technology/NfcF.java new file mode 100644 index 0000000..6741ac8 --- /dev/null +++ b/core/java/android/nfc/technology/NfcF.java @@ -0,0 +1,63 @@ +/* + * 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 new file mode 100644 index 0000000..9b6a16a --- /dev/null +++ b/core/java/android/nfc/technology/NfcV.java @@ -0,0 +1,43 @@ +/* + * 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 { + public NfcV(NfcAdapter adapter, Tag tag, Bundle extras) + throws RemoteException { + super(adapter, tag, TagTechnology.NFC_V); + } +} diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java new file mode 100644 index 0000000..2b4f74c --- /dev/null +++ b/core/java/android/nfc/technology/TagTechnology.java @@ -0,0 +1,109 @@ +/* + * 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 = 11; + + /** + * This object is an instance of {@link NfcV} + */ + public static final int NFC_V = 21; + + /** + * This object is an instance of {@link Ndef} + */ + public static final int TYPE_1 = 101; + + /** + * This object is an instance of {@link Ndef} + */ + public static final int TYPE_2 = 102; + + /** + * This object is an instance of {@link Ndef} + */ + public static final int TYPE_3 = 103; + + /** + * This object is an instance of {@link Ndef} + */ + public static final int TYPE_4 = 104; + + /** + * This object is an instance of {@link MifareClassic} + */ + public static final int MIFARE_CLASSIC = 200; + + /** + * A Mifare Classic tag with NDEF data + */ + public static final int MIFARE_CLASSIC_NDEF = 201; + + /** + * This object is an instance of {@link MifareUltralight} + */ + public static final int MIFARE_ULTRALIGHT = 202; + + /** + * A Mifare DESFire tag + */ + public static final int MIFARE_DESFIRE = 203; + + /** + * 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; + + /** + * 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 new file mode 100644 index 0000000..26b8a32 --- /dev/null +++ b/core/java/android/nfc/technology/package.html @@ -0,0 +1,5 @@ +<HTML> +<BODY> +{@hide} +</BODY> +</HTML>
\ No newline at end of file diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 0c298b0..43d194f 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -111,7 +111,7 @@ public class NumberPicker extends LinearLayout { public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() { final StringBuilder mBuilder = new StringBuilder(); - final java.util.Formatter mFmt = new java.util.Formatter(mBuilder); + final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US); final Object[] mArgs = new Object[1]; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index ced8e9b..a86610d 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -7797,6 +7797,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return new DragThumbnailBuilder(thumbnail); } + private static class DragLocalState { + public TextView sourceTextView; + public int start, end; + + public DragLocalState(TextView sourceTextView, int start, int end) { + this.sourceTextView = sourceTextView; + this.start = start; + this.end = end; + } + } + @Override public boolean performLongClick() { if (super.performLongClick()) { @@ -7822,8 +7833,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int end = getSelectionEnd(); CharSequence selectedText = mTransformed.subSequence(start, end); ClipData data = ClipData.newPlainText(null, null, selectedText); - startDrag(data, getTextThumbnailBuilder(selectedText), false, null); - mDragSourcePositions = packRangeInLong(start, end); + DragLocalState localState = new DragLocalState(this, start, end); + startDrag(data, getTextThumbnailBuilder(selectedText), false, localState); stopSelectionActionMode(); } else { selectCurrentWord(); @@ -8209,6 +8220,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener positionAtCursor(); coords[0] += mPositionX; coords[1] += mPositionY; + coords[0] = Math.max(0, coords[0]); + final int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels; + coords[0] = Math.min(screenWidth - mContainer.getContentView().getMeasuredWidth(), + coords[0]); mContainer.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]); } @@ -8352,7 +8367,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mContainerPositionY = coords[1] + mPositionY; mContainer.showAtLocation(TextView.this, 0, mContainerPositionX, mContainerPositionY); - // Hide paste view when handle is moved. + // Hide paste view when handle is moved on screen. if (mPastePopupWindow != null) { mPastePopupWindow.hide(); } @@ -8491,12 +8506,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mIsDragging = true; if (mHasPastePopupWindow) { mTouchTimer = SystemClock.uptimeMillis(); - if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) { - // Tapping on the handle again dismisses the displayed paste view, - mPastePopupWindow.hide(); - // and makes sure the action up does not display the paste view. - mTouchTimer = 0; - } } break; } @@ -8511,10 +8520,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener break; } case MotionEvent.ACTION_UP: - if (mPastePopupWindow != null) { - // Will show the paste popup after a delay. - mController.show(); - /* TEMP USER TEST: Display Paste as soon as handle is draggged + if (mHasPastePopupWindow) { long delay = SystemClock.uptimeMillis() - mTouchTimer; if (delay < ViewConfiguration.getTapTimeout()) { final float touchOffsetX = ev.getRawX() - mPositionX; @@ -8526,9 +8532,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int doubleTapSlop = viewConfiguration.getScaledDoubleTapSlop(); final int slopSquared = doubleTapSlop * doubleTapSlop; if (distanceSquared < slopSquared) { - showPastePopupWindow(); + if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) { + // Tapping on the handle dismisses the displayed paste view, + mPastePopupWindow.hide(); + } else { + ((InsertionPointCursorController) mController).show(0); + } } - }*/ + } else { + mController.show(); + } } mIsDragging = false; break; @@ -8975,9 +8988,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return true; case DragEvent.ACTION_DRAG_ENDED: - mDragSourcePositions = -1; - return true; - case DragEvent.ACTION_DRAG_EXITED: default: return true; @@ -8995,10 +9005,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int offset = getOffset((int) event.getX(), (int) event.getY()); - if (mDragSourcePositions != -1) { - final int dragSourceStart = extractRangeStartFromLong(mDragSourcePositions); - final int dragSourceEnd = extractRangeEndFromLong(mDragSourcePositions); - if (offset >= dragSourceStart && offset < dragSourceEnd) { + Object localState = event.getLocalState(); + DragLocalState dragLocalState = null; + if (localState instanceof DragLocalState) { + dragLocalState = (DragLocalState) localState; + } + boolean dragDropIntoItself = dragLocalState != null && + dragLocalState.sourceTextView == this; + + if (dragDropIntoItself) { + if (offset >= dragLocalState.start && offset < dragLocalState.end) { // A drop inside the original selection discards the drop. return; } @@ -9012,9 +9028,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Selection.setSelection((Spannable) mText, max); ((Editable) mText).replace(min, max, content); - if (mDragSourcePositions != -1) { - int dragSourceStart = extractRangeStartFromLong(mDragSourcePositions); - int dragSourceEnd = extractRangeEndFromLong(mDragSourcePositions); + if (dragDropIntoItself) { + int dragSourceStart = dragLocalState.start; + int dragSourceEnd = dragLocalState.end; if (max <= dragSourceStart) { // Inserting text before selection has shifted positions final int shift = mText.length() - originalLength; @@ -9198,8 +9214,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private InputFilter[] mFilters = NO_FILTERS; private static final Spanned EMPTY_SPANNED = new SpannedString(""); private static int DRAG_THUMBNAIL_MAX_TEXT_LENGTH = 20; - // A packed range containing the drag source if it occured in that TextView. -1 otherwise. - private long mDragSourcePositions = -1; // System wide time for last cut or copy action. private static long sLastCutOrCopyTime; } diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl index 5d1f632..aee1626 100755 --- a/core/java/com/android/internal/app/IMediaContainerService.aidl +++ b/core/java/com/android/internal/app/IMediaContainerService.aidl @@ -29,5 +29,6 @@ interface IMediaContainerService { in ParcelFileDescriptor outStream); PackageInfoLite getMinimalPackageInfo(in Uri fileUri, int flags); boolean checkFreeStorage(boolean external, in Uri fileUri); - ObbInfo getObbInfo(String filename); + ObbInfo getObbInfo(in String filename); + long calculateDirectorySize(in String directory); } diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 3b2406c..e72e2b6 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -27,6 +27,7 @@ jfieldID gOptions_ditherFieldID; jfieldID gOptions_purgeableFieldID; jfieldID gOptions_shareableFieldID; jfieldID gOptions_nativeAllocFieldID; +jfieldID gOptions_preferQualityOverSpeedFieldID; jfieldID gOptions_widthFieldID; jfieldID gOptions_heightFieldID; jfieldID gOptions_mimeFieldID; @@ -185,6 +186,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, bool isPurgeable = forcePurgeable || (allowPurgeable && optionsPurgeable(env, options)); bool reportSizeToVM = optionsReportSizeToVM(env, options); + bool preferQualityOverSpeed = false; if (NULL != options) { sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); @@ -199,6 +201,8 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, jobject jconfig = env->GetObjectField(options, gOptions_configFieldID); prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig); doDither = env->GetBooleanField(options, gOptions_ditherFieldID); + preferQualityOverSpeed = env->GetBooleanField(options, + gOptions_preferQualityOverSpeedFieldID); } SkImageDecoder* decoder = SkImageDecoder::Factory(stream); @@ -208,6 +212,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, decoder->setSampleSize(sampleSize); decoder->setDitherImage(doDither); + decoder->setPreferQualityOverSpeed(preferQualityOverSpeed); NinePatchPeeker peeker(decoder); JavaPixelAllocator javaAllocator(env, reportSizeToVM); @@ -557,6 +562,8 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) { gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z"); gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z"); gOptions_nativeAllocFieldID = getFieldIDCheck(env, gOptions_class, "inNativeAlloc", "Z"); + gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, gOptions_class, + "inPreferQualityOverSpeed", "Z"); gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I"); gOptions_heightFieldID = getFieldIDCheck(env, gOptions_class, "outHeight", "I"); gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;"); diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h index f868434..9ae61bc 100644 --- a/core/jni/android/graphics/BitmapFactory.h +++ b/core/jni/android/graphics/BitmapFactory.h @@ -11,6 +11,7 @@ extern jfieldID gOptions_ditherFieldID; extern jfieldID gOptions_purgeableFieldID; extern jfieldID gOptions_shareableFieldID; extern jfieldID gOptions_nativeAllocFieldID; +extern jfieldID gOptions_preferQualityOverSpeedFieldID; extern jfieldID gOptions_widthFieldID; extern jfieldID gOptions_heightFieldID; extern jfieldID gOptions_mimeFieldID; diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp index bf18d55..91a8202 100644 --- a/core/jni/android/graphics/BitmapRegionDecoder.cpp +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -191,6 +191,7 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *b int sampleSize = 1; SkBitmap::Config prefConfig = SkBitmap::kNo_Config; bool doDither = true; + bool preferQualityOverSpeed = false; if (NULL != options) { sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); @@ -202,9 +203,12 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *b jobject jconfig = env->GetObjectField(options, gOptions_configFieldID); prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig); doDither = env->GetBooleanField(options, gOptions_ditherFieldID); + preferQualityOverSpeed = env->GetBooleanField(options, + gOptions_preferQualityOverSpeedFieldID); } decoder->setDitherImage(doDither); + decoder->setPreferQualityOverSpeed(preferQualityOverSpeed); SkBitmap* bitmap = new SkBitmap; SkAutoTDelete<SkBitmap> adb(bitmap); AutoDecoderCancel adc(options, decoder); diff --git a/core/res/res/layout/text_edit_no_paste_window.xml b/core/res/res/layout/text_edit_no_paste_window.xml index d409d97..fa50275 100644 --- a/core/res/res/layout/text_edit_no_paste_window.xml +++ b/core/res/res/layout/text_edit_no_paste_window.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 The Android Open Source Project +<!-- 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. @@ -14,34 +14,25 @@ limitations under the License. --> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="@android:drawable/text_edit_paste_window"> - - <ImageView android:id="@+id/paste_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="16dip" - android:paddingRight="8dip" - android:paddingTop="8dip" - android:paddingBottom="8dip" - android:layout_centerVertical="true" - android:background="@android:drawable/ic_menu_paste_dark" - /> + android:layout_height="wrap_content"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingLeft="0dip" + android:paddingLeft="16dip" android:paddingRight="16dip" android:paddingTop="8dip" android:paddingBottom="8dip" - android:layout_centerVertical="true" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@android:string/pasteDisabled" + android:drawableLeft="@android:drawable/ic_menu_paste_dark" + android:drawablePadding="8dip" + android:gravity="center" + android:textAppearance="?android:attr/textAppearanceMediumInverse" android:textColor="@android:color/dim_foreground_dark_inverse_disabled" - android:layout_toRightOf="@id/paste_icon" + android:background="@android:drawable/text_edit_paste_window" + android:text="@android:string/pasteDisabled" + android:layout_marginBottom="12dip" /> -</RelativeLayout> +</LinearLayout> diff --git a/core/res/res/layout/text_edit_paste_window.xml b/core/res/res/layout/text_edit_paste_window.xml index d153365..575b98e 100644 --- a/core/res/res/layout/text_edit_paste_window.xml +++ b/core/res/res/layout/text_edit_paste_window.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 The Android Open Source Project +<!-- 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. @@ -14,34 +14,25 @@ limitations under the License. --> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:background="@android:drawable/text_edit_paste_window"> - - <ImageView android:id="@+id/paste_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="16dip" - android:paddingRight="8dip" - android:paddingTop="8dip" - android:paddingBottom="8dip" - android:layout_centerVertical="true" - android:background="@android:drawable/ic_menu_paste_light" - /> + android:layout_height="wrap_content"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:paddingLeft="0dip" + android:paddingLeft="16dip" android:paddingRight="16dip" android:paddingTop="8dip" android:paddingBottom="8dip" - android:layout_centerVertical="true" + android:drawableLeft="@android:drawable/ic_menu_paste_light" + android:drawablePadding="8dip" + android:gravity="center" android:textAppearance="?android:attr/textAppearanceMediumInverse" - android:text="@android:string/paste" android:textColor="@android:color/black" - android:layout_toRightOf="@id/paste_icon" + android:background="@android:drawable/text_edit_paste_window" + android:text="@android:string/paste" + android:layout_marginBottom="12dip" /> -</RelativeLayout> +</LinearLayout> diff --git a/core/tests/coretests/src/android/net/http/HttpsThroughHttpProxyTest.java b/core/tests/coretests/src/android/net/http/HttpsThroughHttpProxyTest.java deleted file mode 100644 index 95aad91..0000000 --- a/core/tests/coretests/src/android/net/http/HttpsThroughHttpProxyTest.java +++ /dev/null @@ -1,142 +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.net.http; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.List; -import junit.framework.TestCase; -import libcore.javax.net.ssl.TestSSLContext; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.conn.params.ConnRoutePNames; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.ssl.AllowAllHostnameVerifier; -import org.apache.http.conn.ssl.SSLSocketFactory; -import org.apache.http.impl.client.DefaultHttpClient; -import tests.http.MockResponse; -import tests.http.MockWebServer; -import tests.http.RecordedRequest; - -public class HttpsThroughHttpProxyTest extends TestCase { - - public void testConnectViaHttps() throws IOException, InterruptedException { - TestSSLContext testSSLContext = TestSSLContext.create(); - - MockWebServer server = new MockWebServer(); - server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); - server.enqueue(new MockResponse() - .setResponseCode(200) - .setBody("this response comes via HTTPS")); - server.play(); - - HttpClient httpClient = new DefaultHttpClient(); - SSLSocketFactory sslSocketFactory = new SSLSocketFactory( - testSSLContext.clientContext.getSocketFactory()); - sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); - httpClient.getConnectionManager().getSchemeRegistry() - .register(new Scheme("https", sslSocketFactory, server.getPort())); - - HttpResponse response = httpClient.execute( - new HttpGet("https://localhost:" + server.getPort() + "/foo")); - assertEquals("this response comes via HTTPS", contentToString(response)); - - RecordedRequest request = server.takeRequest(); - assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); - } - - /** - * http://code.google.com/p/android/issues/detail?id=2690 - */ - public void testConnectViaProxy() throws IOException, InterruptedException { - MockWebServer proxy = new MockWebServer(); - MockResponse mockResponse = new MockResponse() - .setResponseCode(200) - .setBody("this response comes via a proxy"); - proxy.enqueue(mockResponse); - proxy.play(); - - HttpClient httpProxyClient = new DefaultHttpClient(); - httpProxyClient.getParams().setParameter( - ConnRoutePNames.DEFAULT_PROXY, new HttpHost("localhost", proxy.getPort())); - - HttpResponse response = httpProxyClient.execute(new HttpGet("http://android.com/foo")); - assertEquals("this response comes via a proxy", contentToString(response)); - - RecordedRequest request = proxy.takeRequest(); - assertEquals("GET http://android.com/foo HTTP/1.1", request.getRequestLine()); - assertContains(request.getHeaders(), "Host: android.com"); - } - - public void testConnectViaHttpProxyToHttps() throws IOException, InterruptedException { - TestSSLContext testSSLContext = TestSSLContext.create(); - - MockWebServer proxy = new MockWebServer(); - proxy.useHttps(testSSLContext.serverContext.getSocketFactory(), true); - MockResponse connectResponse = new MockResponse() - .setResponseCode(200); - connectResponse.getHeaders().clear(); - proxy.enqueue(connectResponse); - proxy.enqueue(new MockResponse() - .setResponseCode(200) - .setBody("this response comes via a secure proxy")); - proxy.play(); - - HttpClient httpProxyClient = new DefaultHttpClient(); - HttpHost proxyHost = new HttpHost("localhost", proxy.getPort()); - httpProxyClient.getParams().setParameter( - ConnRoutePNames.DEFAULT_PROXY, proxyHost); - SSLSocketFactory sslSocketFactory = new SSLSocketFactory( - testSSLContext.clientContext.getSocketFactory()); - sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); - httpProxyClient.getConnectionManager().getSchemeRegistry() - .register(new Scheme("https", sslSocketFactory, 443)); - - HttpResponse response = httpProxyClient.execute(new HttpGet("https://android.com/foo")); - assertEquals("this response comes via a secure proxy", contentToString(response)); - - RecordedRequest connect = proxy.takeRequest(); - assertEquals("Connect line failure on proxy " + proxyHost.toHostString(), - "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine()); - assertContains(connect.getHeaders(), "Host: android.com"); - - RecordedRequest get = proxy.takeRequest(); - assertEquals("GET /foo HTTP/1.1", get.getRequestLine()); - assertContains(get.getHeaders(), "Host: android.com"); - } - - private void assertContains(List<String> headers, String header) { - assertTrue(headers.toString(), headers.contains(header)); - } - - private String contentToString(HttpResponse response) throws IOException { - StringWriter writer = new StringWriter(); - char[] buffer = new char[1024]; - Reader reader = new InputStreamReader(response.getEntity().getContent()); - int length; - while ((length = reader.read(buffer)) != -1) { - writer.write(buffer, 0, length); - } - reader.close(); - return writer.toString(); - } -} diff --git a/core/tests/coretests/src/android/net/http/ProxyTest.java b/core/tests/coretests/src/android/net/http/ProxyTest.java new file mode 100644 index 0000000..8175531 --- /dev/null +++ b/core/tests/coretests/src/android/net/http/ProxyTest.java @@ -0,0 +1,266 @@ +/* + * 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.net.http; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringWriter; +import java.util.List; +import junit.framework.TestCase; +import libcore.javax.net.ssl.TestSSLContext; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.params.ConnRoutePNames; +import org.apache.http.conn.params.ConnRouteParams; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.ssl.AllowAllHostnameVerifier; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.impl.client.DefaultHttpClient; +import tests.http.MockResponse; +import tests.http.MockWebServer; +import tests.http.RecordedRequest; + +public class ProxyTest extends TestCase { + + private MockWebServer server = new MockWebServer(); + + @Override protected void tearDown() throws Exception { + System.clearProperty("proxyHost"); + System.clearProperty("proxyPort"); + System.clearProperty("http.proxyHost"); + System.clearProperty("http.proxyPort"); + System.clearProperty("https.proxyHost"); + System.clearProperty("https.proxyPort"); + + server.shutdown(); + super.tearDown(); + } + + public void testConnectToHttps() throws IOException, InterruptedException { + TestSSLContext testSSLContext = TestSSLContext.create(); + + server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); + server.enqueue(new MockResponse() + .setResponseCode(200) + .setBody("this response comes via HTTPS")); + server.play(); + + HttpClient httpClient = new DefaultHttpClient(); + SSLSocketFactory sslSocketFactory = new SSLSocketFactory( + testSSLContext.clientContext.getSocketFactory()); + sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); + httpClient.getConnectionManager().getSchemeRegistry() + .register(new Scheme("https", sslSocketFactory, server.getPort())); + + HttpResponse response = httpClient.execute( + new HttpGet("https://localhost:" + server.getPort() + "/foo")); + assertEquals("this response comes via HTTPS", contentToString(response)); + + RecordedRequest request = server.takeRequest(); + assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); + } + + /** + * We had bugs where proxy system properties weren't being honored. + * http://b/3254717 + */ + public void testConnectViaProxyUsingProxySystemProperty() throws Exception { + testConnectViaProxy(ProxyConfig.PROXY_SYSTEM_PROPERTY); + } + + public void testConnectViaProxyUsingHttpProxySystemProperty() throws Exception { + testConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY); + } + + public void testConnectViaProxyUsingRequestParameter() throws Exception { + testConnectViaProxy(ProxyConfig.REQUEST_PARAMETER); + } + + public void testConnectViaProxyUsingClientParameter() throws Exception { + testConnectViaProxy(ProxyConfig.CLIENT_PARAMETER); + } + + /** + * http://code.google.com/p/android/issues/detail?id=2690 + */ + private void testConnectViaProxy(ProxyConfig proxyConfig) throws Exception { + MockResponse mockResponse = new MockResponse() + .setResponseCode(200) + .setBody("this response comes via a proxy"); + server.enqueue(mockResponse); + server.play(); + + HttpClient httpProxyClient = new DefaultHttpClient(); + + HttpGet request = new HttpGet("http://android.com/foo"); + proxyConfig.configure(server, httpProxyClient, request); + + HttpResponse response = httpProxyClient.execute(request); + assertEquals("this response comes via a proxy", contentToString(response)); + + RecordedRequest get = server.takeRequest(); + assertEquals("GET http://android.com/foo HTTP/1.1", get.getRequestLine()); + assertContains(get.getHeaders(), "Host: android.com"); + } + + public void testConnectViaHttpProxyToHttpsUsingProxySystemProperty() throws Exception { + testConnectViaHttpProxyToHttps(ProxyConfig.PROXY_SYSTEM_PROPERTY); + } + + public void testConnectViaHttpProxyToHttpsUsingHttpsProxySystemProperty() throws Exception { + testConnectViaHttpProxyToHttps(ProxyConfig.HTTPS_PROXY_SYSTEM_PROPERTY); + } + + public void testConnectViaHttpProxyToHttpsUsingClientParameter() throws Exception { + testConnectViaHttpProxyToHttps(ProxyConfig.CLIENT_PARAMETER); + } + + public void testConnectViaHttpProxyToHttpsUsingRequestParameter() throws Exception { + testConnectViaHttpProxyToHttps(ProxyConfig.REQUEST_PARAMETER); + } + + private void testConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception { + TestSSLContext testSSLContext = TestSSLContext.create(); + + server.useHttps(testSSLContext.serverContext.getSocketFactory(), true); + MockResponse connectResponse = new MockResponse() + .setResponseCode(200); + connectResponse.getHeaders().clear(); + server.enqueue(connectResponse); + server.enqueue(new MockResponse() + .setResponseCode(200) + .setBody("this response comes via a secure proxy")); + server.play(); + + HttpClient httpProxyClient = new DefaultHttpClient(); + SSLSocketFactory sslSocketFactory = new SSLSocketFactory( + testSSLContext.clientContext.getSocketFactory()); + sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); + httpProxyClient.getConnectionManager().getSchemeRegistry() + .register(new Scheme("https", sslSocketFactory, 443)); + + HttpGet request = new HttpGet("https://android.com/foo"); + proxyConfig.configure(server, httpProxyClient, request); + + HttpResponse response = httpProxyClient.execute(request); + assertEquals("this response comes via a secure proxy", contentToString(response)); + + RecordedRequest connect = server.takeRequest(); + assertEquals("Connect line failure on proxy " + proxyConfig, + "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine()); + assertContains(connect.getHeaders(), "Host: android.com"); + + RecordedRequest get = server.takeRequest(); + assertEquals("GET /foo HTTP/1.1", get.getRequestLine()); + assertContains(get.getHeaders(), "Host: android.com"); + } + + public void testClientParamPreferredOverSystemProperty() throws Exception { + testParamPreferredOverSystemProperty(ProxyConfig.CLIENT_PARAMETER); + } + + public void testRequestParamPreferredOverSystemProperty() throws Exception { + testParamPreferredOverSystemProperty(ProxyConfig.REQUEST_PARAMETER); + } + + private void testParamPreferredOverSystemProperty(ProxyConfig proxyConfig) throws Exception { + server.enqueue(new MockResponse().setBody("Via request parameter proxy!")); + server.play(); + System.setProperty("http.proxyHost", "proxy.foo"); + System.setProperty("http.proxyPort", "8080"); + + HttpClient client = new DefaultHttpClient(); + HttpGet request = new HttpGet("http://origin.foo/bar"); + proxyConfig.configure(server, client, request); + HttpResponse response = client.execute(request); + assertEquals("Via request parameter proxy!", contentToString(response)); + + RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("GET http://origin.foo/bar HTTP/1.1", recordedRequest.getRequestLine()); + } + + public void testExplicitNoProxyCancelsSystemProperty() throws Exception { + server.enqueue(new MockResponse().setBody("Via the origin server!")); + server.play(); + System.setProperty("http.proxyHost", "proxy.foo"); + System.setProperty("http.proxyPort", "8080"); + + HttpClient client = new DefaultHttpClient(); + HttpGet request = new HttpGet(server.getUrl("/bar").toURI()); + request.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, ConnRouteParams.NO_HOST); + HttpResponse response = client.execute(request); + assertEquals("Via the origin server!", contentToString(response)); + + RecordedRequest recordedRequest = server.takeRequest(); + assertEquals("GET /bar HTTP/1.1", recordedRequest.getRequestLine()); + } + + enum ProxyConfig { + PROXY_SYSTEM_PROPERTY() { + @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { + System.setProperty("proxyHost", "localhost"); + System.setProperty("proxyPort", Integer.toString(server.getPort())); + } + }, + HTTP_PROXY_SYSTEM_PROPERTY() { + @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { + System.setProperty("http.proxyHost", "localhost"); + System.setProperty("http.proxyPort", Integer.toString(server.getPort())); + } + }, + HTTPS_PROXY_SYSTEM_PROPERTY() { + @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { + System.setProperty("https.proxyHost", "localhost"); + System.setProperty("https.proxyPort", Integer.toString(server.getPort())); + } + }, + CLIENT_PARAMETER() { + @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { + client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, + new HttpHost("localhost", server.getPort())); + } + }, + REQUEST_PARAMETER() { + @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { + request.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, + new HttpHost("localhost", server.getPort())); + } + }; + + abstract void configure(MockWebServer proxy, HttpClient client, HttpRequest request); + } + + private void assertContains(List<String> headers, String header) { + assertTrue(headers.toString(), headers.contains(header)); + } + + private String contentToString(HttpResponse response) throws IOException { + StringWriter writer = new StringWriter(); + char[] buffer = new char[1024]; + Reader reader = new InputStreamReader(response.getEntity().getContent()); + int length; + while ((length = reader.read(buffer)) != -1) { + writer.write(buffer, 0, length); + } + reader.close(); + return writer.toString(); + } +} diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index ea5ed6b..8450c3a 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -205,10 +205,21 @@ public class BitmapFactory { public boolean inNativeAlloc; /** + * If inPreferQualityOverSpeed is set to true, the decoder will try to + * decode the reconstructed image to a higher quality even at the + * expense of the decoding speed. Currently the field only affects JPEG + * decode, in the case of which a more accurate, but slightly slower, + * IDCT method will be used instead. + * @hide + */ + public boolean inPreferQualityOverSpeed; + + /** * The resulting width of the bitmap, set independent of the state of * inJustDecodeBounds. However, if there is an error trying to decode, * outWidth will be set to -1. */ + public int outWidth; /** diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h index e6c9f93..794355b 100644 --- a/include/media/stagefright/CameraSource.h +++ b/include/media/stagefright/CameraSource.h @@ -215,6 +215,8 @@ private: status_t checkFrameRate(const CameraParameters& params, int32_t frameRate); + void releaseCamera(); + CameraSource(const CameraSource &); CameraSource &operator=(const CameraSource &); }; diff --git a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh index 7d1721c..24a36c1 100644 --- a/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh +++ b/libs/rs/java/ModelViewer/src/com/android/modelviewer/transform_def.rsh @@ -21,7 +21,7 @@ #define TRANSFORM_ROTATE 2 #define TRANSFORM_SCALE 3 -typedef struct __attribute__((packed, aligned(4))) { +typedef struct __attribute__((packed, aligned(4))) SgTransform { rs_matrix4x4 globalMat; rs_matrix4x4 localMat; diff --git a/libs/rs/java/tests/src/com/android/rs/test/vector_array.rs b/libs/rs/java/tests/src/com/android/rs/test/vector_array.rs index a71a062..49e38c1 100644 --- a/libs/rs/java/tests/src/com/android/rs/test/vector_array.rs +++ b/libs/rs/java/tests/src/com/android/rs/test/vector_array.rs @@ -14,7 +14,7 @@ #include "shared.rsh" -typedef struct { +typedef struct float3Struct{ float3 arr[2]; } float3Struct; diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index cee92d2..f72d919 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -1079,7 +1079,15 @@ status_t StagefrightRecorder::setupCameraSource( mCamera, mCameraId, videoSize, mFrameRate, mPreviewSurface, true /*storeMetaDataInVideoBuffers*/); } - CHECK(*cameraSource != NULL); + if (*cameraSource == NULL) { + return UNKNOWN_ERROR; + } + + if ((*cameraSource)->initCheck() != OK) { + (*cameraSource).clear(); + *cameraSource = NULL; + return NO_INIT; + } // When frame rate is not set, the actual frame rate will be set to // the current frame rate being used. diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index d9ff723..ed9e865 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -130,13 +130,6 @@ CameraSource *CameraSource::CreateFromCamera( CameraSource *source = new CameraSource(camera, cameraId, videoSize, frameRate, surface, storeMetaDataInVideoBuffers); - - if (source != NULL) { - if (source->initCheck() != OK) { - delete source; - return NULL; - } - } return source; } @@ -293,6 +286,7 @@ status_t CameraSource::configureCamera( if (width != -1 && height != -1) { if (!isVideoSizeSupported(width, height, sizes)) { LOGE("Video dimension (%dx%d) is unsupported", width, height); + releaseCamera(); return BAD_VALUE; } if (isSetVideoSizeSupportedByCamera) { @@ -306,6 +300,7 @@ status_t CameraSource::configureCamera( // If one and only one of the width and height is -1 // we reject such a request. LOGE("Requested video size (%dx%d) is not supported", width, height); + releaseCamera(); return BAD_VALUE; } else { // width == -1 && height == -1 // Do not configure the camera. @@ -323,6 +318,7 @@ status_t CameraSource::configureCamera( if (strstr(supportedFrameRates, buf) == NULL) { LOGE("Requested frame rate (%d) is not supported: %s", frameRate, supportedFrameRates); + releaseCamera(); return BAD_VALUE; } @@ -561,6 +557,18 @@ void CameraSource::stopCameraRecording() { mCamera->stopRecording(); } +void CameraSource::releaseCamera() { + LOGV("releaseCamera"); + if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) { + LOGV("Camera was cold when we started, stopping preview"); + mCamera->stopPreview(); + } + mCamera->unlock(); + mCamera.clear(); + mCamera = 0; + mCameraFlags = 0; +} + status_t CameraSource::stop() { LOGV("stop"); Mutex::Autolock autoLock(mLock); @@ -575,16 +583,7 @@ status_t CameraSource::stop() { mFramesBeingEncoded.size()); mFrameCompleteCondition.wait(mLock); } - - LOGV("Disconnect camera"); - if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) { - LOGV("Camera was cold when we started, stopping preview"); - mCamera->stopPreview(); - } - mCamera->unlock(); - mCamera.clear(); - mCamera = 0; - mCameraFlags = 0; + releaseCamera(); IPCThreadState::self()->restoreCallingIdentity(token); if (mCollectStats) { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java index 2332657..ce6db68 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java @@ -253,7 +253,7 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram } //Format: QVGA h263 - @LargeTest + @Suppress public void testQVGAH263() throws Exception { boolean videoRecordedResult = false; recordVideo(15, 320, 240, MediaRecorder.VideoEncoder.H263, @@ -263,7 +263,7 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram } //Format: SQVGA h263 - @LargeTest + @Suppress public void testSQVGAH263() throws Exception { boolean videoRecordedResult = false; recordVideo(15, 240, 160, MediaRecorder.VideoEncoder.H263, @@ -341,7 +341,7 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram assertTrue("HVGAMP4", videoRecordedResult); } - @LargeTest + @Suppress public void testQVGAMP4() throws Exception { boolean videoRecordedResult = false; recordVideo(15, 320, 240, MediaRecorder.VideoEncoder.MPEG_4_SP, @@ -350,7 +350,7 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram assertTrue("QVGAMP4", videoRecordedResult); } - @LargeTest + @Suppress public void testSQVGAMP4() throws Exception { boolean videoRecordedResult = false; recordVideo(15, 240, 160, MediaRecorder.VideoEncoder.MPEG_4_SP, diff --git a/packages/DefaultContainerService/Android.mk b/packages/DefaultContainerService/Android.mk index 2f1d6ab..986b6c8 100755 --- a/packages/DefaultContainerService/Android.mk +++ b/packages/DefaultContainerService/Android.mk @@ -7,6 +7,10 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_PACKAGE_NAME := DefaultContainerService +LOCAL_JNI_SHARED_LIBRARIES := libdefcontainer_jni + LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/DefaultContainerService/jni/Android.mk b/packages/DefaultContainerService/jni/Android.mk new file mode 100644 index 0000000..a2febec --- /dev/null +++ b/packages/DefaultContainerService/jni/Android.mk @@ -0,0 +1,39 @@ +# +# 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. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_PRELINK_MODULE := false + +LOCAL_SRC_FILES := \ + com_android_defcontainer_MeasurementUtils.cpp + +LOCAL_C_INCLUDES += \ + $(JNI_H_INCLUDES) + +LOCAL_SHARED_LIBRARIES := \ + libnativehelper \ + libutils + +LOCAL_STATIC_LIBRARIES := \ + libdiskusage + +LOCAL_MODULE := libdefcontainer_jni +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file diff --git a/packages/DefaultContainerService/jni/com_android_defcontainer_MeasurementUtils.cpp b/packages/DefaultContainerService/jni/com_android_defcontainer_MeasurementUtils.cpp new file mode 100644 index 0000000..6579f95 --- /dev/null +++ b/packages/DefaultContainerService/jni/com_android_defcontainer_MeasurementUtils.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "DefContainer-JNI" + +#include <JNIHelp.h> + +#include <diskusage/dirsize.h> +#include <utils/Log.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> + +namespace android { + +static jlong native_measureDirectory(JNIEnv* env, jobject clazz, jstring directory) { + jlong ret = 0L; + + const char* path = env->GetStringUTFChars(directory, NULL); + if (path == NULL) { + return ret; + } + + int dirfd = open(path, O_DIRECTORY, O_RDONLY); + if (dirfd < 0) { + LOGI("error opening: %s: %s", path, strerror(errno)); + } else { + ret = calculate_dir_size(dirfd); + close(dirfd); + } + + env->ReleaseStringUTFChars(directory, path); + + return ret; +} + +static const JNINativeMethod g_methods[] = { + { "native_measureDirectory", "(Ljava/lang/String;)J", (void*)native_measureDirectory }, +}; + +int register_com_android_defcontainer(JNIEnv *env) { + if (jniRegisterNativeMethods( + env, "com/android/defcontainer/MeasurementUtils", g_methods, NELEM(g_methods)) < 0) { + return JNI_ERR; + } + + return JNI_VERSION_1_6; +} + +} // namespace android + +int JNI_OnLoad(JavaVM *jvm, void* reserved) { + JNIEnv *env; + + if (jvm->GetEnv((void**)&env, JNI_VERSION_1_6)) { + return JNI_ERR; + } + + return android::register_com_android_defcontainer(env); +} diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index e6624ae..0c85af8 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -163,6 +163,11 @@ public class DefaultContainerService extends IntentService { return null; } } + + @Override + public long calculateDirectorySize(String directory) throws RemoteException { + return MeasurementUtils.measureDirectory(directory); + } }; public DefaultContainerService() { diff --git a/core/java/android/nfc/NdefTag.aidl b/packages/DefaultContainerService/src/com/android/defcontainer/MeasurementUtils.java index 288f667..6f5f53b 100644 --- a/core/java/android/nfc/NdefTag.aidl +++ b/packages/DefaultContainerService/src/com/android/defcontainer/MeasurementUtils.java @@ -14,6 +14,16 @@ * limitations under the License. */ -package android.nfc; +package com.android.defcontainer; -parcelable NdefTag;
\ No newline at end of file +public class MeasurementUtils { + static { + System.loadLibrary("defcontainer_jni"); + } + + public static long measureDirectory(String path) { + return native_measureDirectory(path); + } + + private native static long native_measureDirectory(String path); +} diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml index 666bfdc..cd67d1a 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml @@ -76,8 +76,23 @@ android:textColor="#2e2e2e" /> </com.android.systemui.statusbar.tablet.HoloClock> + <TextView + android:id="@+id/network_text" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginTop="12dp" + android:layout_marginRight="6dip" + android:layout_marginLeft="6dip" + android:gravity="center" + android:singleLine="true" + android:visibility="gone" + android:textSize="14dip" + android:textColor="#606060" + /> + <LinearLayout - android:layout_width="48dip" + android:id="@+id/signal_battery_cluster" + android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" android:gravity="center" 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 563b8ef..b0f6a18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -165,6 +165,8 @@ public class TabletStatusBar extends StatusBar { (ImageView)mNotificationPanel.findViewById(R.id.network_type)); mNetworkController.addLabelView( (TextView)mNotificationPanel.findViewById(R.id.network_text)); + mNetworkController.addLabelView( + (TextView)mBarContents.findViewById(R.id.network_text)); mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel); @@ -579,12 +581,28 @@ public class TabletStatusBar extends StatusBar { setAreThereNotifications(); } + public void showClock(boolean show) { + View clock = mBarContents.findViewById(R.id.clock); + View network_text = mBarContents.findViewById(R.id.network_text); + if (clock != null) { + clock.setVisibility(show ? View.VISIBLE : View.GONE); + } + if (network_text != null) { + network_text.setVisibility((!show) ? View.VISIBLE : View.GONE); + } + } + public void disable(int state) { int old = mDisabled; int diff = state ^ old; mDisabled = state; // act accordingly + if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) { + boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0; + Slog.d(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes")); + showClock(show); + } if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) { if ((state & StatusBarManager.DISABLE_EXPAND) != 0) { Slog.d(TAG, "DISABLE_EXPAND: yes"); diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 72af34d..c0c3afd 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -1100,7 +1100,9 @@ public class KeyguardViewMediator implements KeyguardViewCallback, boolean enable = !mShowing || (mHidden && !isSecure()); mStatusBarManager.disable(enable ? StatusBarManager.DISABLE_NONE : - StatusBarManager.DISABLE_EXPAND); + ( StatusBarManager.DISABLE_EXPAND + | StatusBarManager.DISABLE_NAVIGATION + | StatusBarManager.DISABLE_CLOCK)); } } diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 7101bb0..ba8af3a 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -17,7 +17,6 @@ package com.android.server; import com.android.internal.statusbar.StatusBarNotification; -import com.android.server.StatusBarManagerService; import android.app.ActivityManagerNative; import android.app.IActivityManager; @@ -41,12 +40,11 @@ import android.database.ContentObserver; import android.hardware.Usb; import android.media.AudioManager; import android.net.Uri; -import android.os.Bundle; import android.os.Binder; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; -import android.os.Power; import android.os.Process; import android.os.RemoteException; import android.os.SystemProperties; @@ -55,8 +53,8 @@ import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.EventLog; -import android.util.Slog; import android.util.Log; +import android.util.Slog; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; @@ -158,8 +156,6 @@ public class NotificationManagerService extends INotificationManager.Stub final int id; final int uid; final int initialPid; - ITransientNotification callback; - int duration; final Notification notification; IBinder statusBarKey; @@ -642,6 +638,7 @@ public class NotificationManagerService extends INotificationManager.Stub // Notifications // ============================================================================ + @Deprecated public void enqueueNotification(String pkg, int id, Notification notification, int[] idOut) { enqueueNotificationWithTag(pkg, null /* tag */, id, notification, idOut); @@ -975,7 +972,7 @@ public class NotificationManagerService extends INotificationManager.Stub } } - + @Deprecated public void cancelNotification(String pkg, int id) { cancelNotificationWithTag(pkg, null /* tag */, id); } @@ -1030,12 +1027,6 @@ public class NotificationManagerService extends INotificationManager.Stub } } - private void updateLights() { - synchronized (mNotificationList) { - updateLightsLocked(); - } - } - // lock on mNotificationList private void updateLightsLocked() { diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index fce7b9b..b64b45d 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -115,6 +115,7 @@ public abstract class PhoneBase extends Handler implements Phone { int mCallRingContinueToken = 0; int mCallRingDelay; public boolean mIsTheCurrentActivePhone = true; + boolean mIsVoiceCapable = true; /** * Set a system property, unless we're in unit test mode @@ -205,6 +206,15 @@ public abstract class PhoneBase extends Handler implements Phone { mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false); mCM.setOnCallRing(this, EVENT_CALL_RING, null); + /* "Voice capable" means that this device supports circuit-switched + * (i.e. voice) phone calls over the telephony network, and is allowed + * to display the in-call UI while a cellular voice call is active. + * This will be false on "data only" devices which can't make voice + * calls and don't support any in-call UI. + */ + mIsVoiceCapable = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_voice_capable); + /** * Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs * to be generated locally. Ideally all ring tones should be loops @@ -1006,6 +1016,8 @@ public abstract class PhoneBase extends Handler implements Phone { * version scoped to their packages */ protected void notifyNewRingingConnectionP(Connection cn) { + if (!mIsVoiceCapable) + return; AsyncResult ar = new AsyncResult(null, cn, null); mNewRingingConnectionRegistrants.notifyRegistrants(ar); } @@ -1014,6 +1026,8 @@ public abstract class PhoneBase extends Handler implements Phone { * Notify registrants of a RING event. */ private void notifyIncomingRing() { + if (!mIsVoiceCapable) + return; AsyncResult ar = new AsyncResult(null, this, null); mIncomingRingRegistrants.notifyRegistrants(ar); } @@ -1022,7 +1036,8 @@ public abstract class PhoneBase extends Handler implements Phone { * Send the incoming call Ring notification if conditions are right. */ private void sendIncomingCallRingNotification(int token) { - if (!mDoesRilSendMultipleCallRing && (token == mCallRingContinueToken)) { + if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing && + (token == mCallRingContinueToken)) { Log.d(LOG_TAG, "Sending notifyIncomingRing"); notifyIncomingRing(); sendMessageDelayed( @@ -1031,7 +1046,8 @@ public abstract class PhoneBase extends Handler implements Phone { Log.d(LOG_TAG, "Ignoring ring notification request," + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing + " token=" + token - + " mCallRingContinueToken=" + mCallRingContinueToken); + + " mCallRingContinueToken=" + mCallRingContinueToken + + " mIsVoiceCapable=" + mIsVoiceCapable); } } diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml index dc44b25..86b3f06 100644 --- a/tests/DumpRenderTree/AndroidManifest.xml +++ b/tests/DumpRenderTree/AndroidManifest.xml @@ -27,7 +27,7 @@ </activity> <activity android:name="TestShellActivity" android:launchMode="singleTop" - android:hardwareAccelerated="true" + android:hardwareAccelerated="false" android:screenOrientation="portrait" android:theme="@android:style/Theme.Light"/> <activity android:name="ReliabilityTestActivity" android:screenOrientation="portrait" diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java index 132f17a..8aa3c69 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java @@ -20,6 +20,7 @@ import com.android.dumprendertree.TestShellActivity.DumpDataType; import com.android.dumprendertree.forwarder.AdbUtils; import com.android.dumprendertree.forwarder.ForwardService; +import android.content.Context; import android.content.Intent; import android.os.Environment; import android.test.ActivityInstrumentationTestCase2; @@ -471,11 +472,14 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh public void copyResultsAndRunnerAssetsToCache() { try { - String out_dir = getActivity().getApplicationContext().getCacheDir().getPath() + "/"; + Context targetContext = getInstrumentation().getTargetContext(); + File cacheDir = targetContext.getCacheDir(); for( int i=0; i< LAYOUT_TESTS_RESULTS_REFERENCE_FILES.length; i++) { - InputStream in = getActivity().getAssets().open(LAYOUT_TESTS_RESULTS_REFERENCE_FILES[i]); - OutputStream out = new FileOutputStream(out_dir + LAYOUT_TESTS_RESULTS_REFERENCE_FILES[i]); + InputStream in = targetContext.getAssets().open( + LAYOUT_TESTS_RESULTS_REFERENCE_FILES[i]); + OutputStream out = new FileOutputStream(new File(cacheDir, + LAYOUT_TESTS_RESULTS_REFERENCE_FILES[i])); byte[] buf = new byte[2048]; int len; diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java index 9352f39..4982c46 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java @@ -19,6 +19,7 @@ package com.android.dumprendertree; import dalvik.system.VMRuntime; import android.app.Instrumentation; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Debug; @@ -27,6 +28,7 @@ import android.os.Process; import android.test.ActivityInstrumentationTestCase2; import android.util.Log; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -202,14 +204,14 @@ public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShel public void copyRunnerAssetsToCache() { try { - String out_dir = getActivity().getApplicationContext() - .getCacheDir().getPath() + "/"; + Context targetContext = getInstrumentation().getTargetContext(); + File cacheDir = targetContext.getCacheDir(); for( int i=0; i< LOAD_TEST_RUNNER_FILES.length; i++) { - InputStream in = getActivity().getAssets().open( + InputStream in = targetContext.getAssets().open( LOAD_TEST_RUNNER_FILES[i]); OutputStream out = new FileOutputStream( - out_dir + LOAD_TEST_RUNNER_FILES[i]); + new File(cacheDir, LOAD_TEST_RUNNER_FILES[i])); byte[] buf = new byte[2048]; int len; diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java index 7e69ee4..44c7d72 100644 --- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java +++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java @@ -173,22 +173,23 @@ public class StatusBarTest extends TestActivity mStatusBarManager.disable(StatusBarManager.DISABLE_NAVIGATION); } }, + new Test("Disable Clock") { + public void run() { + mStatusBarManager.disable(StatusBarManager.DISABLE_CLOCK); + } + }, new Test("Disable everything in 3 sec") { public void run() { mHandler.postDelayed(new Runnable() { public void run() { - mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND - | StatusBarManager.DISABLE_NOTIFICATION_ICONS - | StatusBarManager.DISABLE_NOTIFICATION_ALERTS - | StatusBarManager.DISABLE_SYSTEM_INFO - | StatusBarManager.DISABLE_NAVIGATION); + mStatusBarManager.disable(~StatusBarManager.DISABLE_NONE); } }, 3000); } }, new Test("Enable everything") { public void run() { - mStatusBarManager.disable(0); + mStatusBarManager.disable(StatusBarManager.DISABLE_NONE); } }, new Test("Enable everything in 3 sec.") { diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java index 212223c..c36b37b 100644 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java +++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java @@ -17,6 +17,7 @@ package android.graphics; import com.android.layoutlib.api.IDensityBasedResourceValue.Density; +import com.android.layoutlib.bridge.Bridge; import android.content.res.AssetManager; import android.content.res.Resources; @@ -448,7 +449,9 @@ public class BitmapFactory { Bitmap bm; if (is instanceof AssetManager.AssetInputStream) { - // FIXME: log this. + Bridge.getLog().error(null, + "Bitmap.decodeStream: " + + "InputStream is unsupported (AssetManager.AssetInputStream)"); return null; } else { // pass some temp storage down to the native code. 1024 is made up, diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index bc6ad64..b116d2b 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -16,7 +16,7 @@ package android.graphics; -import com.android.layoutlib.api.ILayoutLog; +import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.layoutlib.bridge.impl.Stack; @@ -59,7 +59,6 @@ public class Canvas_Delegate { // ---- delegate data ---- private BufferedImage mBufferedImage; private final Stack<Graphics2D> mGraphicsStack = new Stack<Graphics2D>(); - private ILayoutLog mLogger; // ---- Public Helper methods ---- @@ -78,14 +77,6 @@ public class Canvas_Delegate { } /** - * Sets the layoutlib logger into the canvas. - * @param logger - */ - public void setLogger(ILayoutLog logger) { - mLogger = logger; - } - - /** * Returns the current {@link Graphics2D} used to draw. */ public Graphics2D getGraphics2d() { @@ -408,10 +399,11 @@ public class Canvas_Delegate { // give it to the graphics2D as a new matrix replacing all previous transform g.setTransform(matrixTx); - // FIXME: log -// if (mLogger != null && matrixDelegate.hasPerspective()) { -// mLogger.warning("android.graphics.Canvas#setMatrix(android.graphics.Matrix) only supports affine transformations in the Layout Editor."); -// } + if (matrixDelegate.hasPerspective()) { + Bridge.getLog().warning(null, + "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " + + "supports affine transformations in the Layout Preview."); + } } /*package*/ static boolean native_clipRect(int nCanvas, @@ -1042,11 +1034,10 @@ public class Canvas_Delegate { g.setPaint(shaderPaint); useColorPaint = false; } else { - if (mLogger != null) { - mLogger.warning(String.format( - "Shader '%1$s' is not supported in the Layout Editor.", + Bridge.getLog().warning(null, + String.format( + "Shader '%1$s' is not supported in the Layout Preview.", shaderDelegate.getClass().getCanonicalName())); - } } } @@ -1089,10 +1080,11 @@ public class Canvas_Delegate { g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); // if xfermode wasn't null, then it's something we don't support. log it. - if (mLogger != null && xfermodeDelegate != null) { - mLogger.warning(String.format( - "Xfermode '%1$s' is not supported in the Layout Editor.", - xfermodeDelegate.getClass().getCanonicalName())); + if (xfermodeDelegate != null) { + Bridge.getLog().warning(null, + String.format( + "Xfermode '%1$s' is not supported in the Layout Preview.", + xfermodeDelegate.getClass().getCanonicalName())); } } diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java index 3d26e47..a6c6dfd 100644 --- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java @@ -16,6 +16,7 @@ package android.graphics; +import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.ninepatch.NinePatchChunk; @@ -71,7 +72,7 @@ public class NinePatch_Delegate { oos = new ObjectOutputStream(baos); oos.writeObject(chunk); } catch (IOException e) { - //FIXME log this. + Bridge.getLog().error("Failed to serialize NinePatchChunk.", e); return null; } finally { if (oos != null) { @@ -205,10 +206,10 @@ public class NinePatch_Delegate { sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); } } catch (IOException e) { - // FIXME: log this + Bridge.getLog().error("Failed to deserialize NinePatchChunk content.", e); return null; } catch (ClassNotFoundException e) { - // FIXME: log this + Bridge.getLog().error("Failed to deserialize NinePatchChunk class.", e); return null; } finally { if (ois != null) { diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index 93f757a..c09f8ad 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -340,6 +340,7 @@ public class Paint_Delegate { } delegate.mTextSize = textSize; + delegate.updateFontObject(); } /*package*/ static float getTextScaleX(Paint thisPaint) { @@ -362,6 +363,7 @@ public class Paint_Delegate { } delegate.mTextScaleX = scaleX; + delegate.updateFontObject(); } /*package*/ static float getTextSkewX(Paint thisPaint) { @@ -384,6 +386,7 @@ public class Paint_Delegate { } delegate.mTextSkewX = skewX; + delegate.updateFontObject(); } /*package*/ static float ascent(Paint thisPaint) { @@ -662,7 +665,9 @@ public class Paint_Delegate { return 0; } - return delegate.mTypeface = typeface; + delegate.mTypeface = typeface; + delegate.updateFontObject(); + return delegate.mTypeface; } /*package*/ static int native_setRasterizer(int native_object, int rasterizer) { @@ -670,7 +675,6 @@ public class Paint_Delegate { throw new UnsupportedOperationException(); } - /*package*/ static int native_getTextAlign(int native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); @@ -810,14 +814,10 @@ public class Paint_Delegate { private Paint_Delegate() { reset(); - - mTypeface = Typeface.sDefaults[0].native_instance; - updateFontObject(); } private Paint_Delegate(Paint_Delegate paint) { set(paint); - updateFontObject(); } private void set(Paint_Delegate paint) { @@ -838,6 +838,7 @@ public class Paint_Delegate { mShader = paint.mShader; mPathEffect = paint.mPathEffect; mMaskFilter = paint.mMaskFilter; + updateFontObject(); } private void reset() { @@ -847,7 +848,7 @@ public class Paint_Delegate { mCap = 0; mJoin = 0; mTextAlign = 0; - mTypeface = 0; + mTypeface = Typeface.sDefaults[0].native_instance; mStrokeWidth = 1.f; mStrokeMiter = 2.f; mTextSize = 20.f; @@ -858,6 +859,7 @@ public class Paint_Delegate { mShader = 0; mPathEffect = 0; mMaskFilter = 0; + updateFontObject(); } /** diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index 2a94774..38e03ca 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -17,7 +17,7 @@ package com.android.layoutlib.bridge; import com.android.layoutlib.api.Capabilities; -import com.android.layoutlib.api.ILayoutLog; +import com.android.layoutlib.api.LayoutLog; import com.android.layoutlib.api.IProjectCallback; import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.api.IXmlPullParser; @@ -133,14 +133,16 @@ public final class Bridge extends LayoutBridge { private final static IntArray sIntArrayWrapper = new IntArray(); /** - * A default logger than prints to stdout/stderr. + * A default log than prints to stdout/stderr. */ - private final static ILayoutLog sDefaultLogger = new ILayoutLog() { - public void error(String message) { + private final static LayoutLog sDefaultLog = new LayoutLog() { + @Override + public void error(String tag, String message) { System.err.println(message); } - public void error(Throwable t) { + @Override + public void error(String tag, Throwable t) { String message = t.getMessage(); if (message == null) { message = t.getClass().getName(); @@ -149,11 +151,23 @@ public final class Bridge extends LayoutBridge { System.err.println(message); } - public void warning(String message) { + @Override + public void error(String tag, String message, Throwable throwable) { + System.err.println(message); + } + + @Override + public void warning(String tag, String message) { System.out.println(message); } }; + /** + * Current log. + */ + private static LayoutLog sCurrentLog = sDefaultLog; + + private EnumSet<Capabilities> mCapabilities; @@ -203,7 +217,7 @@ public final class Bridge extends LayoutBridge { OverrideMethod.setDefaultListener(new MethodAdapter() { @Override public void onInvokeV(String signature, boolean isNative, Object caller) { - sDefaultLogger.error("Missing Stub: " + signature + + sDefaultLog.error(null, "Missing Stub: " + signature + (isNative ? " (native)" : "")); if (debug.equalsIgnoreCase("throw")) { @@ -311,7 +325,7 @@ public final class Bridge extends LayoutBridge { @Override public BridgeLayoutScene createScene(SceneParams params) { try { - SceneResult lastResult = SceneStatus.SUCCESS.getResult(); + SceneResult lastResult = SceneStatus.SUCCESS.createResult(); LayoutSceneImpl scene = new LayoutSceneImpl(params); try { prepareThread(); @@ -335,7 +349,7 @@ public final class Bridge extends LayoutBridge { t2 = t.getCause(); } return new BridgeLayoutScene(null, - SceneStatus.ERROR_UNKNOWN.getResult(t2.getMessage(), t2)); + SceneStatus.ERROR_UNKNOWN.createResult(t2.getMessage(), t2)); } } @@ -383,6 +397,23 @@ public final class Bridge extends LayoutBridge { Looper.sThreadLocal.remove(); } + public static LayoutLog getLog() { + return sCurrentLog; + } + + public static void setLog(LayoutLog log) { + // check only the thread currently owning the lock can do this. + if (sLock.isHeldByCurrentThread() == false) { + throw new IllegalStateException("scene must be acquired first. see #acquire(long)"); + } + + if (log != null) { + sCurrentLog = log; + } else { + sCurrentLog = sDefaultLog; + } + } + /** * Returns details of a framework resource from its integer value. * @param value the integer value @@ -391,7 +422,6 @@ public final class Bridge extends LayoutBridge { */ public static String[] resolveResourceValue(int value) { return sRMap.get(value); - } /** diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 688f240..32b2fd4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -16,7 +16,6 @@ package com.android.layoutlib.bridge.android; -import com.android.layoutlib.api.ILayoutLog; import com.android.layoutlib.api.IProjectCallback; import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.api.IStyleResourceValue; @@ -97,7 +96,6 @@ public final class BridgeContext extends Activity { private BridgeInflater mInflater; private final IProjectCallback mProjectCallback; - private final ILayoutLog mLogger; private BridgeContentResolver mContentResolver; private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>(); @@ -122,11 +120,10 @@ public final class BridgeContext extends Activity { Map<String, Map<String, IResourceValue>> projectResources, Map<String, Map<String, IResourceValue>> frameworkResources, Map<IStyleResourceValue, IStyleResourceValue> styleInheritanceMap, - IProjectCallback projectCallback, ILayoutLog logger) { + IProjectCallback projectCallback) { mProjectKey = projectKey; mMetrics = metrics; mProjectCallback = projectCallback; - mLogger = logger; mThemeValues = currentTheme; mProjectResources = projectResources; @@ -183,10 +180,6 @@ public final class BridgeContext extends Activity { return mProjectCallback; } - public ILayoutLog getLogger() { - return mLogger; - } - public Map<String, String> getDefaultPropMap(Object key) { return mDefaultPropMaps.get(key); } @@ -340,7 +333,7 @@ public final class BridgeContext extends Activity { // good, nothing to do. } else if (set != null) { // null parser is ok // really this should not be happening since its instantiated in Bridge - mLogger.error("Parser is not a BridgeXmlBlockParser!"); + Bridge.getLog().error(null, "Parser is not a BridgeXmlBlockParser!"); return null; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java index d9e26e2..057c9c3 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java @@ -178,7 +178,7 @@ public final class BridgeInflater extends LayoutInflater { return inflate(bridgeParser, root); } catch (Exception e) { - bridgeContext.getLogger().error(e); + Bridge.getLog().error(null, e); // return null below. } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java index affd1c6..678be9c 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java @@ -174,11 +174,11 @@ public final class BridgeResources extends Resources { return ColorStateList.createFromXml(this, new BridgeXmlBlockParser(parser, mContext, resValue.isFramework())); } catch (XmlPullParserException e) { - mContext.getLogger().error(e); + Bridge.getLog().error(null, e); } catch (FileNotFoundException e) { // will not happen, since we pre-check } catch (IOException e) { - mContext.getLogger().error(e); + Bridge.getLog().error(null, e); } } else { @@ -245,7 +245,7 @@ public final class BridgeResources extends Resources { return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); } } catch (XmlPullParserException e) { - mContext.getLogger().error(e); + Bridge.getLog().error(null, e); // we'll return null below. } catch (FileNotFoundException e) { // this shouldn't happen since we check above. @@ -279,7 +279,7 @@ public final class BridgeResources extends Resources { return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); } } catch (XmlPullParserException e) { - mContext.getLogger().error(e); + Bridge.getLog().error(null, e); // we'll return null below. } catch (FileNotFoundException e) { // this shouldn't happen since we check above. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java index c8dc9e6..800256b 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java @@ -205,7 +205,7 @@ public final class BridgeTypedArray extends TypedArray { if (i != null) { result |= i.intValue(); } else { - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unknown constant \"%s\" in attribute \"%2$s\"", keyword, mNames[index])); } @@ -235,7 +235,7 @@ public final class BridgeTypedArray extends TypedArray { try { return Float.parseFloat(s); } catch (NumberFormatException e) { - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unable to convert \"%s\" into a float in attribute \"%2$s\"", s, mNames[index])); @@ -267,7 +267,7 @@ public final class BridgeTypedArray extends TypedArray { try { return ResourceHelper.getColor(s); } catch (NumberFormatException e) { - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unable to convert \"%s\" into a color in attribute \"%2$s\"", s, mNames[index])); @@ -322,13 +322,13 @@ public final class BridgeTypedArray extends TypedArray { } catch (Exception e) { // this is an error and not warning since the file existence is checked before // attempting to parse it. - mContext.getLogger().error(e); + Bridge.getLog().error(null, e); // return null below. } // looks like were unable to resolve the color value. - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unable to resolve color value \"%1$s\" in attribute \"%2$s\"", value, mNames[index])); @@ -356,7 +356,7 @@ public final class BridgeTypedArray extends TypedArray { try { return Integer.parseInt(s); } catch (NumberFormatException e) { - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unable to convert \"%s\" into a integer in attribute \"%2$s\"", s, mNames[index])); @@ -405,7 +405,7 @@ public final class BridgeTypedArray extends TypedArray { } // looks like we were unable to resolve the dimension value - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unable to resolve dimension value \"%1$s\" in attribute \"%2$s\"", s, mNames[index])); @@ -534,7 +534,7 @@ public final class BridgeTypedArray extends TypedArray { } // looks like we were unable to resolve the fraction value - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unable to resolve fraction value \"%1$s\" in attribute \"%2$s\"", value, mNames[index])); @@ -641,7 +641,7 @@ public final class BridgeTypedArray extends TypedArray { return idValue.intValue(); } - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index])); return defValue; } @@ -675,7 +675,7 @@ public final class BridgeTypedArray extends TypedArray { } // looks like we were unable to resolve the drawable - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( "Unable to resolve drawable \"%1$s\" in attribute \"%2$s\"", stringValue, mNames[index])); @@ -704,7 +704,7 @@ public final class BridgeTypedArray extends TypedArray { return new CharSequence[] { value }; } - mContext.getLogger().warning(String.format( + Bridge.getLog().warning(null, String.format( String.format("Unknown value for getTextArray(%d) => %s", //DEBUG index, mData[index].getName()))); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java index 400a05f..4ee813c 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/AnimationThread.java @@ -146,7 +146,7 @@ public abstract class AnimationThread extends Thread { } } while (mListener.isCanceled() == false && mQueue.size() > 0); - mListener.done(SceneStatus.SUCCESS.getResult()); + mListener.done(SceneStatus.SUCCESS.createResult()); } finally { postAnimation(); Handler_Delegate.setCallback(null); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java index 359180f..d58cde8 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java @@ -50,7 +50,6 @@ import android.app.Fragment_Delegate; import android.graphics.Bitmap; import android.graphics.Bitmap_Delegate; import android.graphics.Canvas; -import android.graphics.Canvas_Delegate; import android.graphics.drawable.Drawable; import android.os.Handler; import android.util.DisplayMetrics; @@ -174,7 +173,7 @@ public class LayoutSceneImpl { // build the context mContext = new BridgeContext(mParams.getProjectKey(), metrics, mCurrentTheme, mParams.getProjectResources(), mParams.getFrameworkResources(), - styleParentMap, mParams.getProjectCallback(), mParams.getLogger()); + styleParentMap, mParams.getProjectCallback()); // set the current rendering context sCurrentContext = mContext; @@ -202,7 +201,7 @@ public class LayoutSceneImpl { mBlockParser = new BridgeXmlBlockParser(mParams.getLayoutDescription(), mContext, false /* platformResourceFlag */); - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } /** @@ -243,8 +242,9 @@ public class LayoutSceneImpl { // scene mContext.initResources(); sCurrentContext = mContext; + Bridge.setLog(mParams.getLog()); - return SUCCESS.getResult(); + return SUCCESS.createResult(); } /** @@ -267,10 +267,10 @@ public class LayoutSceneImpl { boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); if (acquired == false) { - return ERROR_TIMEOUT.getResult(); + return ERROR_TIMEOUT.createResult(); } } catch (InterruptedException e) { - return ERROR_LOCK_INTERRUPTED.getResult(); + return ERROR_LOCK_INTERRUPTED.createResult(); } } else { // This thread holds the lock already. Checks that this wasn't for a different context. @@ -279,7 +279,7 @@ public class LayoutSceneImpl { if (mContext != sCurrentContext) { throw new IllegalStateException("Acquiring different scenes from same thread without releases"); } - return SUCCESS.getResult(); + return SUCCESS.createResult(); } return null; @@ -297,6 +297,7 @@ public class LayoutSceneImpl { if (lock.isHeldByCurrentThread()) { // Make sure to remove static references, otherwise we could not unload the lib mContext.disposeResources(); + Bridge.setLog(null); sCurrentContext = null; lock.unlock(); @@ -344,9 +345,9 @@ public class LayoutSceneImpl { mViewRoot.setBackgroundDrawable(d); } - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } catch (PostInflateException e) { - return SceneStatus.ERROR_INFLATION.getResult(e.getMessage(), e); + return SceneStatus.ERROR_INFLATION.createResult(e.getMessage(), e); } catch (Throwable e) { // get the real cause of the exception. Throwable t = e; @@ -355,9 +356,9 @@ public class LayoutSceneImpl { } // log it - mParams.getLogger().error(t); + mParams.getLog().error("Scene inflate failed", t); - return SceneStatus.ERROR_INFLATION.getResult(t.getMessage(), t); + return SceneStatus.ERROR_INFLATION.createResult(t.getMessage(), t); } } @@ -377,7 +378,7 @@ public class LayoutSceneImpl { try { if (mViewRoot == null) { - return SceneStatus.ERROR_NOT_INFLATED.getResult(); + return SceneStatus.ERROR_NOT_INFLATED.createResult(); } // measure the views int w_spec, h_spec; @@ -457,10 +458,6 @@ public class LayoutSceneImpl { mCanvas.setDensity(mParams.getDensity()); } - // to set the logger, get the native delegate - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(mCanvas); - canvasDelegate.setLogger(mParams.getLogger()); - long preDrawTime = System.currentTimeMillis(); mViewRoot.draw(mCanvas); @@ -472,7 +469,7 @@ public class LayoutSceneImpl { System.out.println(String.format("rendering (ms): %03d", drawTime - preDrawTime)); // success! - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } catch (Throwable e) { // get the real cause of the exception. Throwable t = e; @@ -481,9 +478,9 @@ public class LayoutSceneImpl { } // log it - mParams.getLogger().error(t); + mParams.getLog().error("Scene Render failed", t); - return SceneStatus.ERROR_UNKNOWN.getResult(t.getMessage(), t); + return SceneStatus.ERROR_UNKNOWN.createResult(t.getMessage(), t); } } @@ -524,7 +521,7 @@ public class LayoutSceneImpl { new PlayAnimationThread(anim, this, animationName, listener).start(); - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } } catch (Exception e) { // get the real cause of the exception. @@ -533,11 +530,11 @@ public class LayoutSceneImpl { t = t.getCause(); } - return SceneStatus.ERROR_UNKNOWN.getResult(t.getMessage(), t); + return SceneStatus.ERROR_UNKNOWN.createResult(t.getMessage(), t); } } - return SceneStatus.ERROR_ANIM_NOT_FOUND.getResult(); + return SceneStatus.ERROR_ANIM_NOT_FOUND.createResult(); } /** @@ -581,7 +578,7 @@ public class LayoutSceneImpl { }.start(); // always return success since the real status will come through the listener. - return SceneStatus.SUCCESS.getResult(child); + return SceneStatus.SUCCESS.createResult(child); } // add it to the parentView in the correct location @@ -612,10 +609,10 @@ public class LayoutSceneImpl { private SceneResult addView(ViewGroup parent, View view, int index) { try { parent.addView(view, index); - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } catch (UnsupportedOperationException e) { // looks like this is a view class that doesn't support children manipulation! - return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.getResult(); + return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.createResult(); } } @@ -659,7 +656,7 @@ public class LayoutSceneImpl { }.start(); // always return success since the real status will come through the listener. - return SceneStatus.SUCCESS.getResult(layoutParams); + return SceneStatus.SUCCESS.createResult(layoutParams); } SceneResult result = moveView(parentView, childView, index, layoutParams); @@ -701,10 +698,10 @@ public class LayoutSceneImpl { parent.addView(view, index); } - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } catch (UnsupportedOperationException e) { // looks like this is a view class that doesn't support children manipulation! - return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.getResult(); + return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.createResult(); } } @@ -741,7 +738,7 @@ public class LayoutSceneImpl { }.start(); // always return success since the real status will come through the listener. - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } SceneResult result = removeView(parent, childView); @@ -764,10 +761,10 @@ public class LayoutSceneImpl { private SceneResult removeView(ViewGroup parent, View view) { try { parent.removeView(view); - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } catch (UnsupportedOperationException e) { // looks like this is a view class that doesn't support children manipulation! - return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.getResult(); + return SceneStatus.ERROR_VIEWGROUP_NO_CHILDREN.createResult(); } } @@ -927,7 +924,7 @@ public class LayoutSceneImpl { return (IStyleResourceValue)parent; } - mParams.getLogger().error( + mParams.getLog().error(null, String.format("Unable to resolve parent style name: %s", parentName)); return null; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java index bbc7f4b..2e2c5f4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java @@ -38,7 +38,7 @@ public class PlayAnimationThread extends AnimationThread { // the queue is filled when this method returns. mAnimator.start(); - return SceneStatus.SUCCESS.getResult(); + return SceneStatus.SUCCESS.createResult(); } @Override diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java index ceb8a0d..5a4a0a5 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java @@ -17,8 +17,8 @@ package com.android.layoutlib.bridge.impl; import com.android.layoutlib.api.IDensityBasedResourceValue; -import com.android.layoutlib.api.IDensityBasedResourceValue.Density; import com.android.layoutlib.api.IResourceValue; +import com.android.layoutlib.api.IDensityBasedResourceValue.Density; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; @@ -188,11 +188,11 @@ public final class ResourceHelper { new BridgeXmlBlockParser(parser, context, isFramework)); return d; } catch (XmlPullParserException e) { - context.getLogger().error(e); + Bridge.getLog().error(null, e); } catch (FileNotFoundException e) { // will not happen, since we pre-check } catch (IOException e) { - context.getLogger().error(e); + Bridge.getLog().error(null, e); } } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 4828700b..18385b7 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -924,7 +924,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { } /** - * TODO: doc + * Request a wakelock with connectivity service to + * keep the device awake until we hand-off from wifi + * to an alternate network */ public void requestCmWakeLock() { sendMessage(CMD_REQUEST_CM_WAKELOCK); @@ -2143,6 +2145,8 @@ public class WifiStateMachine extends HierarchicalStateMachine { Log.d(TAG, "set frequency band " + band); if (WifiNative.setBandCommand(band)) { mFrequencyBand.set(band); + //Fetch the latest scan results when frequency band is set + startScan(true); } else { Log.e(TAG, "Failed to set frequency band " + band); } @@ -2153,13 +2157,6 @@ public class WifiStateMachine extends HierarchicalStateMachine { transitionTo(mDriverStoppingState); mWakeLock.release(); break; - case CMD_REQUEST_CM_WAKELOCK: - if (mCm == null) { - mCm = (ConnectivityManager)mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - } - mCm.requestNetworkTransitionWakelock(TAG); - break; case CMD_START_PACKET_FILTERING: WifiNative.startPacketFiltering(); break; @@ -2637,6 +2634,13 @@ public class WifiStateMachine extends HierarchicalStateMachine { sendMessage(CMD_DISCONNECT); deferMessage(message); break; + case CMD_REQUEST_CM_WAKELOCK: + if (mCm == null) { + mCm = (ConnectivityManager)mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + } + mCm.requestNetworkTransitionWakelock(TAG); + break; case CMD_SET_SCAN_MODE: if (message.arg1 == SCAN_ONLY_MODE) { sendMessage(CMD_DISCONNECT); |