diff options
39 files changed, 717 insertions, 899 deletions
diff --git a/api/10.xml b/api/10.xml index 3b9ab1a0edfc..15fcffe71640 100644 --- a/api/10.xml +++ b/api/10.xml @@ -157967,21 +157967,6 @@ <parameter name="flags" type="int"> </parameter> </method> -<method name="setPackageObbPath" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="packageName" type="java.lang.String"> -</parameter> -<parameter name="path" type="java.lang.String"> -</parameter> -</method> </class> <class name="MockResources" extends="android.content.res.Resources" diff --git a/api/9.xml b/api/9.xml index 3b9ab1a0edfc..15fcffe71640 100644 --- a/api/9.xml +++ b/api/9.xml @@ -157967,21 +157967,6 @@ <parameter name="flags" type="int"> </parameter> </method> -<method name="setPackageObbPath" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="packageName" type="java.lang.String"> -</parameter> -<parameter name="path" type="java.lang.String"> -</parameter> -</method> </class> <class name="MockResources" extends="android.content.res.Resources" diff --git a/api/current.xml b/api/current.xml index 4006e67a0f05..588338180685 100644 --- a/api/current.xml +++ b/api/current.xml @@ -45984,19 +45984,6 @@ <exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException"> </exception> </method> -<method name="getPackageObbPaths" - return="java.lang.String[]" - abstract="true" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="packageName" type="java.lang.String"> -</parameter> -</method> <method name="getPackagesForUid" return="java.lang.String[]" abstract="true" @@ -46468,21 +46455,6 @@ <parameter name="flags" type="int"> </parameter> </method> -<method name="setPackageObbPaths" - return="void" - abstract="true" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="packageName" type="java.lang.String"> -</parameter> -<parameter name="paths" type="java.lang.String[]"> -</parameter> -</method> <field name="COMPONENT_ENABLED_STATE_DEFAULT" type="int" transient="false" @@ -100830,6 +100802,19 @@ <parameter name="activity" type="android.app.Activity"> </parameter> </method> +<method name="disableForegroundNdefPush" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="activity" type="android.app.Activity"> +</parameter> +</method> <method name="enableForegroundDispatch" return="void" abstract="false" @@ -100847,6 +100832,21 @@ <parameter name="filters" type="android.content.IntentFilter..."> </parameter> </method> +<method name="enableForegroundNdefPush" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="activity" type="android.app.Activity"> +</parameter> +<parameter name="msg" type="android.nfc.NdefMessage"> +</parameter> +</method> <method name="getDefaultAdapter" return="android.nfc.NfcAdapter" abstract="false" @@ -101083,17 +101083,6 @@ > <implements name="android.nfc.technology.TagTechnology"> </implements> -<method name="checkConnected" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> <method name="close" return="void" abstract="false" @@ -101164,7 +101153,16 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> -<method name="transceive" +</class> +<class name="IsoDep" + extends="android.nfc.technology.BasicTagTechnology" + abstract="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<method name="getHiLayerResponse" return="byte[]" abstract="false" native="false" @@ -101174,37 +101172,19 @@ deprecated="not deprecated" visibility="public" > -<parameter name="data" type="byte[]"> -</parameter> -<exception name="IOException" type="java.io.IOException"> -</exception> </method> -</class> -<class name="IsoDep" - extends="android.nfc.technology.BasicTagTechnology" +<method name="getHistoricalBytes" + return="byte[]" abstract="false" - static="false" - final="true" - deprecated="not deprecated" - visibility="public" -> -<constructor name="IsoDep" - type="android.nfc.technology.IsoDep" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="adapter" type="android.nfc.NfcAdapter"> -</parameter> -<parameter name="tag" type="android.nfc.Tag"> -</parameter> -<parameter name="extras" type="android.os.Bundle"> -</parameter> -<exception name="RemoteException" type="android.os.RemoteException"> -</exception> -</constructor> -<method name="getHiLayerResponse" +</method> +<method name="transceive" return="byte[]" abstract="false" native="false" @@ -101214,9 +101194,13 @@ deprecated="not deprecated" visibility="public" > +<parameter name="data" type="byte[]"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> </method> -<method name="getHistoricalBytes" - return="byte[]" +<method name="setTimeout" + return="void" abstract="false" native="false" synchronized="false" @@ -101225,6 +101209,8 @@ deprecated="not deprecated" visibility="public" > +<parameter name="timeout" type="int"> +</parameter> </method> </class> <class name="MifareClassic" @@ -101235,22 +101221,6 @@ deprecated="not deprecated" visibility="public" > -<constructor name="MifareClassic" - type="android.nfc.technology.MifareClassic" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="adapter" type="android.nfc.NfcAdapter"> -</parameter> -<parameter name="tag" type="android.nfc.Tag"> -</parameter> -<parameter name="extras" type="android.os.Bundle"> -</parameter> -<exception name="RemoteException" type="android.os.RemoteException"> -</exception> -</constructor> <method name="authenticateBlock" return="boolean" abstract="false" @@ -101443,6 +101413,21 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> +<method name="transceive" + return="byte[]" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="data" type="byte[]"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> +</method> <method name="transfer" return="void" abstract="false" @@ -101593,17 +101578,6 @@ visibility="public" > </field> -<field name="TYPE_DESFIRE" - type="int" - transient="false" - volatile="false" - value="3" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="TYPE_PLUS" type="int" transient="false" @@ -101626,17 +101600,6 @@ visibility="public" > </field> -<field name="TYPE_ULTRALIGHT" - type="int" - transient="false" - volatile="false" - value="4" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="TYPE_UNKNOWN" type="int" transient="false" @@ -101657,22 +101620,6 @@ deprecated="not deprecated" visibility="public" > -<constructor name="MifareUltralight" - type="android.nfc.technology.MifareUltralight" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="adapter" type="android.nfc.NfcAdapter"> -</parameter> -<parameter name="tag" type="android.nfc.Tag"> -</parameter> -<parameter name="extras" type="android.os.Bundle"> -</parameter> -<exception name="RemoteException" type="android.os.RemoteException"> -</exception> -</constructor> <method name="getType" return="int" abstract="false" @@ -101694,12 +101641,12 @@ deprecated="not deprecated" visibility="public" > -<parameter name="block" type="int"> +<parameter name="page" type="int"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> </method> -<method name="readOTP" +<method name="transceive" return="byte[]" abstract="false" native="false" @@ -101709,21 +101656,6 @@ deprecated="not deprecated" visibility="public" > -<exception name="IOException" type="java.io.IOException"> -</exception> -</method> -<method name="writeBlock" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="block" type="int"> -</parameter> <parameter name="data" type="byte[]"> </parameter> <exception name="IOException" type="java.io.IOException"> @@ -101739,7 +101671,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="block" type="int"> +<parameter name="page" type="int"> </parameter> <parameter name="data" type="byte[]"> </parameter> @@ -101810,21 +101742,6 @@ visibility="public" > </method> -<method name="getExtraNdefMessage" - return="android.nfc.NdefMessage[]" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<exception name="FormatException" type="android.nfc.FormatException"> -</exception> -<exception name="IOException" type="java.io.IOException"> -</exception> -</method> <method name="getMaxSize" return="int" abstract="false" @@ -101886,25 +101803,6 @@ <exception name="IOException" type="java.io.IOException"> </exception> </method> -<method name="writeExtraNdefMessage" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="i" type="int"> -</parameter> -<parameter name="msg" type="android.nfc.NdefMessage"> -</parameter> -<exception name="FormatException" type="android.nfc.FormatException"> -</exception> -<exception name="IOException" type="java.io.IOException"> -</exception> -</method> <method name="writeNdefMessage" return="void" abstract="false" @@ -102023,24 +101921,19 @@ deprecated="not deprecated" visibility="public" > -<constructor name="NfcA" - type="android.nfc.technology.NfcA" +<method name="getAtqa" + return="byte[]" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="adapter" type="android.nfc.NfcAdapter"> -</parameter> -<parameter name="tag" type="android.nfc.Tag"> -</parameter> -<parameter name="extras" type="android.os.Bundle"> -</parameter> -<exception name="RemoteException" type="android.os.RemoteException"> -</exception> -</constructor> -<method name="getAtqa" - return="byte[]" +</method> +<method name="getSak" + return="short" abstract="false" native="false" synchronized="false" @@ -102050,8 +101943,8 @@ visibility="public" > </method> -<method name="getSak" - return="short" +<method name="transceive" + return="byte[]" abstract="false" native="false" synchronized="false" @@ -102060,6 +101953,10 @@ deprecated="not deprecated" visibility="public" > +<parameter name="data" type="byte[]"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> </method> </class> <class name="NfcB" @@ -102070,23 +101967,18 @@ deprecated="not deprecated" visibility="public" > -<constructor name="NfcB" - type="android.nfc.technology.NfcB" +<method name="getApplicationData" + return="byte[]" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="adapter" type="android.nfc.NfcAdapter"> -</parameter> -<parameter name="tag" type="android.nfc.Tag"> -</parameter> -<parameter name="extras" type="android.os.Bundle"> -</parameter> -<exception name="RemoteException" type="android.os.RemoteException"> -</exception> -</constructor> -<method name="getApplicationData" +</method> +<method name="getProtocolInfo" return="byte[]" abstract="false" native="false" @@ -102097,7 +101989,7 @@ visibility="public" > </method> -<method name="getProtocolInfo" +<method name="transceive" return="byte[]" abstract="false" native="false" @@ -102107,6 +101999,10 @@ deprecated="not deprecated" visibility="public" > +<parameter name="data" type="byte[]"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> </method> </class> <class name="NfcF" @@ -102117,23 +102013,18 @@ deprecated="not deprecated" visibility="public" > -<constructor name="NfcF" - type="android.nfc.technology.NfcF" +<method name="getManufacturer" + return="byte[]" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="adapter" type="android.nfc.NfcAdapter"> -</parameter> -<parameter name="tag" type="android.nfc.Tag"> -</parameter> -<parameter name="extras" type="android.os.Bundle"> -</parameter> -<exception name="RemoteException" type="android.os.RemoteException"> -</exception> -</constructor> -<method name="getManufacturer" +</method> +<method name="getSystemCode" return="byte[]" abstract="false" native="false" @@ -102144,7 +102035,7 @@ visibility="public" > </method> -<method name="getSystemCode" +<method name="transceive" return="byte[]" abstract="false" native="false" @@ -102154,6 +102045,10 @@ deprecated="not deprecated" visibility="public" > +<parameter name="data" type="byte[]"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> </method> </class> <class name="NfcV" @@ -102164,23 +102059,18 @@ deprecated="not deprecated" visibility="public" > -<constructor name="NfcV" - type="android.nfc.technology.NfcV" +<method name="getDsfId" + return="byte" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="adapter" type="android.nfc.NfcAdapter"> -</parameter> -<parameter name="tag" type="android.nfc.Tag"> -</parameter> -<parameter name="extras" type="android.os.Bundle"> -</parameter> -<exception name="RemoteException" type="android.os.RemoteException"> -</exception> -</constructor> -<method name="getDsfId" +</method> +<method name="getResponseFlags" return="byte" abstract="false" native="false" @@ -102191,8 +102081,8 @@ visibility="public" > </method> -<method name="getResponseFlags" - return="byte" +<method name="transceive" + return="byte[]" abstract="false" native="false" synchronized="false" @@ -102201,6 +102091,10 @@ deprecated="not deprecated" visibility="public" > +<parameter name="data" type="byte[]"> +</parameter> +<exception name="IOException" type="java.io.IOException"> +</exception> </method> </class> <interface name="TagTechnology" @@ -159724,19 +159618,6 @@ <exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException"> </exception> </method> -<method name="getPackageObbPaths" - return="java.lang.String[]" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="packageName" type="java.lang.String"> -</parameter> -</method> <method name="getPackagesForUid" return="java.lang.String[]" abstract="false" @@ -160206,36 +160087,6 @@ <parameter name="flags" type="int"> </parameter> </method> -<method name="setPackageObbPath" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="packageName" type="java.lang.String"> -</parameter> -<parameter name="path" type="java.lang.String"> -</parameter> -</method> -<method name="setPackageObbPaths" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="packageName" type="java.lang.String"> -</parameter> -<parameter name="paths" type="java.lang.String[]"> -</parameter> -</method> </class> <class name="MockResources" extends="android.content.res.Resources" @@ -226827,7 +226678,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="t" type="T"> +<parameter name="arg0" type="T"> </parameter> </method> </interface> diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index e3fa32c4b059..162d9eb8ea25 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1439,6 +1439,16 @@ public final class ActivityThread { } } + public void unregisterOnActivityPausedListener(Activity activity, + OnActivityPausedListener listener) { + synchronized (mOnPauseListeners) { + ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity); + if (list != null) { + list.remove(listener); + } + } + } + public final ActivityInfo resolveActivityInfo(Intent intent) { ActivityInfo aInfo = intent.resolveActivityInfo( mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 18ab478b2360..50ec34f6a301 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2699,25 +2699,6 @@ class ContextImpl extends Context { return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; } - @Override - public void setPackageObbPaths(String packageName, String[] paths) { - try { - mPM.setPackageObbPaths(packageName, paths); - } catch (RemoteException e) { - // Should never happen! - } - } - - @Override - public String[] getPackageObbPaths(String packageName) { - try { - return mPM.getPackageObbPaths(packageName); - } catch (RemoteException e) { - // Should never happen! - } - return null; - } - private final ContextImpl mContext; private final IPackageManager mPM; diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 44b0c9653743..bfc9185708d5 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -321,7 +321,4 @@ interface IPackageManager { boolean setInstallLocation(int loc); int getInstallLocation(); - - void setPackageObbPaths(in String packageName, in String[] paths); - String[] getPackageObbPaths(in String packageName); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index a1c29f774dc3..922f8cd0e81a 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2271,32 +2271,4 @@ public abstract class PackageManager { */ public abstract void movePackage( String packageName, IPackageMoveObserver observer, int flags); - - /** - * Sets the Opaque Binary Blob (OBB) file path associated with a package - * name. The caller must have the - * {@link android.Manifest.permission#INSTALL_PACKAGES} permission. - * <p> - * NOTE: The existence or format of this file is not currently checked, but - * it may be in the future. - * - * @param packageName Name of the package with which to associate the .obb - * file. - * @param paths Arrays of paths on the filesystem to the .obb files - * associated with the package. - * @see #getPackageObbPaths(String) - */ - public abstract void setPackageObbPaths(String packageName, String[] paths); - - /** - * Gets the Opaque Binary Blob (OBB) file path associated with the package. - * The caller must be the owner of the package queried or have the - * {@link android.Manifest.permission#INSTALL_PACKAGES} permission. - * - * @param packageName Name of the package with which to associate the .obb - * file. - * @return array of paths to .obb files associated with the package - * @see #setPackageObbPaths(String, String[]) - */ - public abstract String[] getPackageObbPaths(String packageName); } diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index cb9fc9d05fbe..cfeff523581d 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -50,6 +50,8 @@ interface INfcAdapter void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent, in IntentFilter[] filters); void disableForegroundDispatch(in ComponentName activity); + void enableForegroundNdefPush(in ComponentName activity, in NdefMessage msg); + void disableForegroundNdefPush(in ComponentName activity); // Non-public methods // TODO: check and complete diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl index 5d222d909a19..300eeaa2dda1 100644 --- a/core/java/android/nfc/INfcTag.aidl +++ b/core/java/android/nfc/INfcTag.aidl @@ -39,4 +39,7 @@ interface INfcTag int ndefMakeReadOnly(int nativeHandle); boolean ndefIsWritable(int nativeHandle); int formatNdef(int nativeHandle, in byte[] key); + + void setIsoDepTimeout(int timeout); + void resetIsoDepTimeout(); } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index c0c0462bfe8c..f6605b855761 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -413,13 +413,6 @@ public final class NfcAdapter { } } - class ForegroundDispatchPausedListener implements OnActivityPausedListener { - @Override - public void onPaused(Activity activity) { - disableForegroundDispatchInternal(activity, true); - } - } - /** * Enables foreground dispatching to the given Activity. This will force all NFC Intents that * match the given filters to be delivered to the activity bypassing the standard dispatch @@ -438,12 +431,12 @@ public final class NfcAdapter { throw new NullPointerException(); } if (!activity.isResumed()) { - throw new IllegalStateException("Foregorund dispatching can onlly be enabled " + + throw new IllegalStateException("Foregorund dispatching can only be enabled " + "when your activity is resumed"); } try { ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, - new ForegroundDispatchPausedListener()); + mForegroundDispatchListener); sService.enableForegroundDispatch(activity.getComponentName(), intent, filters); } catch (RemoteException e) { attemptDeadServiceRecovery(e); @@ -452,15 +445,26 @@ public final class NfcAdapter { /** * Disables foreground activity dispatching setup with - * {@link #enableForegroundDispatch}. This must be called before the Activity returns from + * {@link #enableForegroundDispatch}. + * + * <p>This must be called before the Activity returns from * it's <code>onPause()</code> or this method will throw an IllegalStateException. * - * This method must be called from the main thread. + * <p>This method must be called from the main thread. */ public void disableForegroundDispatch(Activity activity) { + ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, + mForegroundDispatchListener); disableForegroundDispatchInternal(activity, false); } + OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() { + @Override + public void onPaused(Activity activity) { + disableForegroundDispatchInternal(activity, true); + } + }; + void disableForegroundDispatchInternal(Activity activity, boolean force) { try { sService.disableForegroundDispatch(activity.getComponentName()); @@ -474,6 +478,60 @@ public final class NfcAdapter { } /** + * Enable NDEF messages push while this Activity is in the foreground. + */ + public void enableForegroundNdefPush(Activity activity, NdefMessage msg) { + if (activity == null || msg == null) { + throw new NullPointerException(); + } + if (!activity.isResumed()) { + throw new IllegalStateException("Foregorund NDEF push can only be enabled " + + "when your activity is resumed"); + } + try { + ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity, + mForegroundNdefPushListener); + sService.enableForegroundNdefPush(activity.getComponentName(), msg); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } + } + + /** + * Disables foreground NDEF push setup with + * {@link #enableForegroundNdefPush}. + * + * <p>This must be called before the Activity returns from + * it's <code>onPause()</code> or this method will throw an IllegalStateException. + * + * <p>This method must be called from the main thread. + */ + public void disableForegroundNdefPush(Activity activity) { + ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity, + mForegroundNdefPushListener); + disableForegroundNdefPushInternal(activity, false); + } + + OnActivityPausedListener mForegroundNdefPushListener = new OnActivityPausedListener() { + @Override + public void onPaused(Activity activity) { + disableForegroundNdefPushInternal(activity, true); + } + }; + + void disableForegroundNdefPushInternal(Activity activity, boolean force) { + try { + sService.disableForegroundNdefPush(activity.getComponentName()); + if (!force && !activity.isResumed()) { + throw new IllegalStateException("You must disable forgeground NDEF push " + + "while your activity is still resumed"); + } + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } + } + + /** * Retrieve a TagTechnology object used to interact with a Tag that is * in field. * <p> diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java index 7bd22891b7d5..8e2360ac1145 100644 --- a/core/java/android/nfc/Tag.java +++ b/core/java/android/nfc/Tag.java @@ -36,8 +36,8 @@ import java.util.Arrays; /** * Represents a (generic) discovered tag. * <p> - * A tag is a passive NFC element, such as NFC Forum Tag's, Mifare class Tags, - * Sony Felica Tags. + * A tag is a passive NFC element, such as NFC Forum Tag's, MIFARE class Tags, + * Sony FeliCa Tags, etc. * <p> * Tag's have a type and usually have a UID. * <p> diff --git a/core/java/android/nfc/technology/BasicTagTechnology.java b/core/java/android/nfc/technology/BasicTagTechnology.java index f529ee554ef9..6d3292b242b0 100644 --- a/core/java/android/nfc/technology/BasicTagTechnology.java +++ b/core/java/android/nfc/technology/BasicTagTechnology.java @@ -39,10 +39,7 @@ import android.util.Log; /*package*/ final INfcAdapter mService; /*package*/ final INfcTag mTagService; - /** - * @hide - */ - public BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException { + BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException { int[] techList = tag.getTechnologyList(); int i; @@ -64,46 +61,36 @@ import android.util.Log; mSelectedTechnology = tech; } - /** - * @hide - */ - public BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException { + BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException { this(adapter, tag, tag.getTechnologyList()[0]); } - /** - * Get the {@link Tag} this connection is associated with. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - */ @Override public Tag getTag() { return mTag; } - public void checkConnected() { + /** Internal helper to throw IllegalStateException if the technology isn't connected */ + void checkConnected() { if ((mTag.getConnectedTechnology() != getTechnologyId()) || (mTag.getConnectedTechnology() == -1)) { throw new IllegalStateException("Call connect() first!"); } } - /** - * <p>Requires {@link android.Manifest.permission#NFC} permission. - */ @Override public int getTechnologyId() { return mSelectedTechnology; } /** - * Helper to indicate if {@link #transceive transceive()} calls might succeed. + * Helper to indicate if {@link #connect} has succeeded. * <p> * Does not cause RF activity, and does not block. - * <p>Requires {@link android.Manifest.permission#NFC} permission. * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed * to be within range. Applications must still handle {@link java.io.IOException} - * while using {@link #transceive transceive()}, in case connection is lost after this method - * returns true. + * while using methods that require a connection in case the connection is lost after this + * method returns. */ public boolean isConnected() { if (!mIsConnected) { @@ -118,16 +105,6 @@ import android.util.Log; } } - /** - * Connect to the {@link Tag} associated with this connection. - * <p> - * This method blocks until the connection is established. - * <p> - * {@link #close} can be called from another thread to cancel this connection - * attempt. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - * @throws IOException if the target is lost, or connect canceled - */ @Override public void connect() throws IOException { try { @@ -146,17 +123,6 @@ import android.util.Log; } } - /** - * Re-connect to the {@link Tag} associated with this connection. - * <p> - * Reconnecting to a tag can be used to reset the state of the tag itself. - * This method blocks until the connection is re-established. - * <p> - * {@link #close} can be called from another thread to cancel this connection - * attempt. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - * @throws IOException if the target is lost, or connect canceled - */ @Override public void reconnect() throws IOException { if (!mIsConnected) { @@ -179,16 +145,6 @@ import android.util.Log; } } - /** - * Close this connection. - * <p> - * Causes blocking operations such as {@link #transceive transceive()} or {@link #connect} to - * be canceled and immediately throw {@link java.io.IOException}. - * <p> - * Once this method is called, this object cannot be re-used and should be discarded. Further - * calls to {@link #transceive transceive()} or {@link #connect} will fail. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - */ @Override public void close() { try { @@ -204,7 +160,7 @@ import android.util.Log; } } - /** internal transceive */ + /** Internal transceive */ /*package*/ byte[] transceive(byte[] data, boolean raw) throws IOException { checkConnected(); @@ -219,19 +175,4 @@ import android.util.Log; throw new IOException("NFC service died"); } } - - /** - * Send data to a tag and receive the response. - * <p> - * This method will block until the response is received. It can be canceled - * with {@link #close}. - * <p>Requires {@link android.Manifest.permission#NFC} permission. - * - * @param data bytes to send - * @return bytes received in response - * @throws IOException if the target is lost or connection closed - */ - public byte[] transceive(byte[] data) throws IOException { - return transceive(data, true); - } } diff --git a/core/java/android/nfc/technology/IsoDep.java b/core/java/android/nfc/technology/IsoDep.java index 03c518e72a24..4b4efa46f94a 100644 --- a/core/java/android/nfc/technology/IsoDep.java +++ b/core/java/android/nfc/technology/IsoDep.java @@ -20,6 +20,7 @@ import android.nfc.NfcAdapter; import android.nfc.Tag; import android.os.Bundle; import android.os.RemoteException; +import android.util.Log; import java.io.IOException; @@ -38,6 +39,8 @@ import java.io.IOException; * permission. */ public final class IsoDep extends BasicTagTechnology { + private static final String TAG = "NFC"; + /** @hide */ public static final String EXTRA_HI_LAYER_RESP = "hiresp"; /** @hide */ @@ -46,6 +49,7 @@ public final class IsoDep extends BasicTagTechnology { private byte[] mHiLayerResponse = null; private byte[] mHistBytes = null; + /** @hide */ public IsoDep(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException { super(adapter, tag, TagTechnology.ISO_DEP); @@ -56,16 +60,58 @@ public final class IsoDep extends BasicTagTechnology { } /** - * 3A only + * Sets the timeout of an IsoDep transceive transaction in milliseconds. + * If the transaction has not completed before the timeout, + * any ongoing {@link BasicTagTechnology#transceive} operation will be + * aborted and the connection to the tag is lost. This setting is applied + * only to the {@link Tag} object linked to this technology and will be + * reset when {@link IsoDep#close} is called. + * The default transaction timeout is 5 seconds. + */ + public void setTimeout(int timeout) { + try { + mTagService.setIsoDepTimeout(timeout); + } catch (RemoteException e) { + Log.e(TAG, "NFC service dead", e); + } + } + + @Override + public void close() { + try { + mTagService.resetIsoDepTimeout(); + } catch (RemoteException e) { + Log.e(TAG, "NFC service dead", e); + } + super.close(); + } + + /** + * Return the historical bytes if the tag is using {@link NfcA}, null otherwise. */ public byte[] getHistoricalBytes() { return mHistBytes; } /** - * 3B only + * Return the hi layer response bytes if the tag is using {@link NfcB}, null otherwise. */ public byte[] getHiLayerResponse() { return mHiLayerResponse; } + + /** + * Send data to a tag and receive the response. + * <p> + * This method will block until the response is received. It can be canceled + * with {@link #close}. + * <p>Requires {@link android.Manifest.permission#NFC} permission. + * + * @param data bytes to send + * @return bytes received in response + * @throws IOException if the target is lost or connection closed + */ + public byte[] transceive(byte[] data) throws IOException { + return transceive(data, true); + } } diff --git a/core/java/android/nfc/technology/MifareClassic.java b/core/java/android/nfc/technology/MifareClassic.java index 3be38fe81860..fc3e8b3a93fa 100644 --- a/core/java/android/nfc/technology/MifareClassic.java +++ b/core/java/android/nfc/technology/MifareClassic.java @@ -24,21 +24,22 @@ import android.os.RemoteException; import java.io.IOException; /** - * Concrete class for TagTechnology.MIFARE_CLASSIC + * Technology class representing MIFARE Classic tags (also known as MIFARE Standard). * - * 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. + * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology + * MIFARE Classic tags will still be scanned, but will only show the NfcA technology. * - * Each sector has k blocks. - * Block size is constant across the whole MIFARE classic family. + * <p>MIFARE Classic tags have sectors that each contain blocks. The block size is constant at + * 16 bytes, but the number of sectors and the sector size varies by product. MIFARE has encryption + * built in and each sector has two keys associated with it, as well as ACLs to determine what + * level acess each key grants. Before operating on a sector you must call either + * {@link #authenticateSector(int, byte[], boolean)} or + * {@link #authenticateBlock(int, byte[], boolean)} to gain authorize your request. */ public final class MifareClassic extends BasicTagTechnology { /** - * The well-known, default MIFARE read key. - * Use this key to effectively make the payload in this sector - * public. + * The well-known default MIFARE read key. All keys are set to this at the factory. + * Using this key will effectively make the payload in the sector public. */ public static final byte[] KEY_DEFAULT = {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF}; @@ -53,39 +54,45 @@ public final class MifareClassic extends BasicTagTechnology { public static final byte[] KEY_NFC_FORUM = {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7}; + /** A MIFARE Classic tag */ public static final int TYPE_CLASSIC = 0; + /** A MIFARE Plus tag */ public static final int TYPE_PLUS = 1; + /** A MIFARE Pro tag */ public static final int TYPE_PRO = 2; - public static final int TYPE_DESFIRE = 3; - public static final int TYPE_ULTRALIGHT = 4; + /** The tag type is unknown */ public static final int TYPE_UNKNOWN = 5; + /** The tag contains 16 sectors, each holding 4 blocks. */ public static final int SIZE_1K = 1024; + /** The tag contains 32 sectors, each holding 4 blocks. */ public static final int SIZE_2K = 2048; + /** + * The tag contains 40 sectors. The first 32 sectors contain 4 blocks and the last 8 sectors + * contain 16 blocks. + */ public static final int SIZE_4K = 4096; + /** The tag contains 5 sectors, each holding 4 blocks. */ public static final int SIZE_MINI = 320; + /** The capacity is unknown */ public static final int SIZE_UNKNOWN = 0; private boolean mIsEmulated; private int mType; private int mSize; + /** @hide */ public MifareClassic(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException { super(adapter, tag, TagTechnology.MIFARE_CLASSIC); - // Check if this could actually be a Mifare + // Check if this could actually be a MIFARE Classic NfcA a = (NfcA) adapter.getTechnology(tag, 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 @@ -122,7 +129,7 @@ public final class MifareClassic extends BasicTagTechnology { // TODO this really should be a short, not byte if (a.getAtqa()[0] == 0x03) { // Type == DESFIRE - mType = TYPE_DESFIRE; + break; } else { // Type == MF+ // SL = SL3 @@ -160,27 +167,25 @@ public final class MifareClassic extends BasicTagTechnology { mType = TYPE_PRO; mSize = SIZE_4K; break; - default: - // Unknown mifare - mType = TYPE_UNKNOWN; - mSize = SIZE_UNKNOWN; - break; } } - // Immutable data known at discovery time + /** Returns the size of the tag, determined at discovery time */ public int getSize() { return mSize; } + /** Returns the size of the tag, determined at discovery time */ public int getType() { return mType; } + /** Returns true if the tag is emulated, determined at discovery time */ public boolean isEmulated() { return mIsEmulated; } + /** Returns the number of sectors on this tag, determined at discovery time */ public int getSectorCount() { switch (mSize) { case SIZE_1K: { @@ -201,10 +206,12 @@ public final class MifareClassic extends BasicTagTechnology { } } + /** Returns the sector size, determined at discovery time */ public int getSectorSize(int sector) { return getBlockCount(sector) * 16; } + /** Returns the total block count, determined at discovery time */ public int getTotalBlockCount() { int totalBlocks = 0; for (int sec = 0; sec < getSectorCount(); sec++) { @@ -214,6 +221,7 @@ public final class MifareClassic extends BasicTagTechnology { return totalBlocks; } + /** Returns the block count for the given sector, determined at discovery time */ public int getBlockCount(int sector) { if (sector >= getSectorCount()) { throw new IllegalArgumentException("this card only has " + getSectorCount() + @@ -237,8 +245,8 @@ public final class MifareClassic extends BasicTagTechnology { // Methods that require connect() /** - * Authenticate for a given block. - * Note that this will authenticate the entire sector the block belongs to. + * Authenticate the entire sector that the given block resides in. + * <p>This requires a that the tag be connected. */ public boolean authenticateBlock(int block, byte[] key, boolean keyA) { checkConnected(); @@ -274,6 +282,7 @@ public final class MifareClassic extends BasicTagTechnology { /** * Authenticate for a given sector. + * <p>This requires a that the tag be connected. */ public boolean authenticateSector(int sector, byte[] key, boolean keyA) { checkConnected(); @@ -288,6 +297,7 @@ public final class MifareClassic extends BasicTagTechnology { /** * Sector indexing starts at 0. * Block indexing starts at 0, and resets in each sector. + * <p>This requires a that the tag be connected. * @throws IOException */ public byte[] readBlock(int sector, int block) throws IOException { @@ -295,11 +305,11 @@ public final class MifareClassic extends BasicTagTechnology { byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff); return readBlock(addr); - } /** * Reads absolute block index. + * <p>This requires a that the tag be connected. * @throws IOException */ public byte[] readBlock(int block) throws IOException { @@ -313,6 +323,7 @@ public final class MifareClassic extends BasicTagTechnology { /** * Writes absolute block index. + * <p>This requires a that the tag be connected. * @throws IOException */ public void writeBlock(int block, byte[] data) throws IOException { @@ -329,6 +340,7 @@ public final class MifareClassic extends BasicTagTechnology { /** * Writes relative block in sector. + * <p>This requires a that the tag be connected. * @throws IOException */ public void writeBlock(int sector, int block, byte[] data) throws IOException { @@ -342,7 +354,6 @@ public final class MifareClassic extends BasicTagTechnology { public void increment(int block) throws IOException { checkConnected(); - byte addr = (byte) block; byte[] incr_cmd = { (byte) 0xC1, (byte) block }; transceive(incr_cmd, false); @@ -351,7 +362,6 @@ public final class MifareClassic extends BasicTagTechnology { public void decrement(int block) throws IOException { checkConnected(); - byte addr = (byte) block; byte[] decr_cmd = { (byte) 0xC0, (byte) block }; transceive(decr_cmd, false); @@ -360,7 +370,6 @@ public final class MifareClassic extends BasicTagTechnology { public void transfer(int block) throws IOException { checkConnected(); - byte addr = (byte) block; byte[] trans_cmd = { (byte) 0xB0, (byte) block }; transceive(trans_cmd, false); @@ -369,9 +378,24 @@ public final class MifareClassic extends BasicTagTechnology { public void restore(int block) throws IOException { checkConnected(); - byte addr = (byte) block; byte[] rest_cmd = { (byte) 0xC2, (byte) block }; transceive(rest_cmd, false); } + + /** + * Send raw NfcA data to a tag and receive the response. + * <p> + * This method will block until the response is received. It can be canceled + * with {@link #close}. + * <p>Requires {@link android.Manifest.permission#NFC} permission. + * <p>This requires a that the tag be connected. + * + * @param data bytes to send + * @return bytes received in response + * @throws IOException if the target is lost or connection closed + */ + public byte[] transceive(byte[] data) throws IOException { + return transceive(data, true); + } } diff --git a/core/java/android/nfc/technology/MifareUltralight.java b/core/java/android/nfc/technology/MifareUltralight.java index 525b85bb8fca..5c8cb3cba47a 100644 --- a/core/java/android/nfc/technology/MifareUltralight.java +++ b/core/java/android/nfc/technology/MifareUltralight.java @@ -16,33 +16,35 @@ package android.nfc.technology; -import java.io.IOException; - 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 + * Technology class representing MIFARE Ultralight and MIFARE Ultralight C tags. * - * MIFARE Ultralight has n sectors, with varying sizes, although - * they are at least the same pattern for any one MIFARE Ultralight - * product. Each sector has two keys. Authentication with the correct - * key is needed before access to any sector. + * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology + * MIFARE Ultralight class tags will still be scanned, but will only show the NfcA technology. * - * Each sector has k blocks. - * Block size is constant across the whole MIFARE Ultralight family. + * <p>MIFARE Ultralight class tags have a series of 4 bytes pages that can be individually written + * and read in chunks of 4 for a total read of 16 bytes. */ public final class MifareUltralight extends BasicTagTechnology { + /** A MIFARE Ultralight tag */ public static final int TYPE_ULTRALIGHT = 1; + /** A MIFARE Ultralight C tag */ public static final int TYPE_ULTRALIGHT_C = 2; + /** The tag type is unknown */ public static final int TYPE_UNKNOWN = 10; private static final int NXP_MANUFACTURER_ID = 0x04; private int mType; + /** @hide */ public MifareUltralight(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException { super(adapter, tag, TagTechnology.MIFARE_ULTRALIGHT); @@ -57,49 +59,59 @@ public final class MifareUltralight extends BasicTagTechnology { } } + /** Returns the type of the tag */ public int getType() { return mType; } // Methods that require connect() /** + * Reads a single 16 byte block from the given page offset. + * + * <p>This requires a that the tag be connected. + * * @throws IOException */ - public byte[] readBlock(int block) throws IOException { + public byte[] readBlock(int page) throws IOException { checkConnected(); - byte[] blockread_cmd = { 0x30, (byte)block }; // phHal_eMifareRead + byte[] blockread_cmd = { 0x30, (byte) page}; // phHal_eMifareRead return transceive(blockread_cmd, false); } /** + * Writes a 4 byte page to the tag. + * + * <p>This requires a that the tag be connected. + * + * @param page The offset of the page to write + * @param data The data to write * @throws IOException */ - public byte[] readOTP() throws IOException { - checkConnected(); - - return readBlock(3); // OTP is at page 3 - } - - public void writePage(int block, byte[] data) throws IOException { + public void writePage(int page, byte[] data) throws IOException { checkConnected(); byte[] pagewrite_cmd = new byte[data.length + 2]; pagewrite_cmd[0] = (byte) 0xA2; - pagewrite_cmd[1] = (byte) block; + pagewrite_cmd[1] = (byte) page; System.arraycopy(data, 0, pagewrite_cmd, 2, data.length); transceive(pagewrite_cmd, false); } - public void writeBlock(int block, byte[] data) throws IOException { - checkConnected(); - - byte[] blockwrite_cmd = new byte[data.length + 2]; - blockwrite_cmd[0] = (byte) 0xA0; - blockwrite_cmd[1] = (byte) block; - System.arraycopy(data, 0, blockwrite_cmd, 2, data.length); - - transceive(blockwrite_cmd, false); + /** + * Send raw NfcA data to a tag and receive the response. + * <p> + * This method will block until the response is received. It can be canceled + * with {@link #close}. + * <p>Requires {@link android.Manifest.permission#NFC} permission. + * <p>This requires a that the tag be connected. + * + * @param data bytes to send + * @return bytes received in response + * @throws IOException if the target is lost or connection closed + */ + public byte[] transceive(byte[] data) throws IOException { + return transceive(data, true); } } diff --git a/core/java/android/nfc/technology/Ndef.java b/core/java/android/nfc/technology/Ndef.java index 5f05b58d506d..f537941c79c7 100644 --- a/core/java/android/nfc/technology/Ndef.java +++ b/core/java/android/nfc/technology/Ndef.java @@ -100,15 +100,6 @@ public final class Ndef extends BasicTagTechnology { } /** - * Get optional extra NDEF messages. - * Some tags may contain extra NDEF messages, but not all - * implementations will be able to read them. - */ - public NdefMessage[] getExtraNdefMessage() throws IOException, FormatException { - throw new UnsupportedOperationException(); - } - - /** * Get NDEF tag type. * <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2}, * {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4}, @@ -208,22 +199,6 @@ public final class Ndef extends BasicTagTechnology { } /** - * 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 { - checkConnected(); - - throw new UnsupportedOperationException(); - } - - /** * Indicates whether a tag can be made read-only with * {@link #makeReadonly()} */ @@ -246,28 +221,26 @@ public final class Ndef extends BasicTagTechnology { checkConnected(); try { - int errorCode = mTagService.ndefMakeReadOnly(mTag.getServiceHandle()); - switch (errorCode) { - case ErrorCodes.SUCCESS: - return true; - case ErrorCodes.ERROR_IO: - throw new IOException(); - case ErrorCodes.ERROR_INVALID_PARAM: - return false; - default: - // Should not happen - throw new IOException(); - } + if (mTagService.isNdef(mTag.getServiceHandle())) { + int errorCode = mTagService.ndefMakeReadOnly(mTag.getServiceHandle()); + switch (errorCode) { + case ErrorCodes.SUCCESS: + return true; + case ErrorCodes.ERROR_IO: + throw new IOException(); + case ErrorCodes.ERROR_INVALID_PARAM: + return false; + default: + // Should not happen + throw new IOException(); + } + } + else { + throw new IOException("Tag is not ndef"); + } } catch (RemoteException e) { Log.e(TAG, "NFC service dead", e); return false; } } - - @Override - public byte[] transceive(byte[] data) { - checkConnected(); - - throw new UnsupportedOperationException(); - } } diff --git a/core/java/android/nfc/technology/NdefFormatable.java b/core/java/android/nfc/technology/NdefFormatable.java index 0901607ad1e8..e2fd03440331 100644 --- a/core/java/android/nfc/technology/NdefFormatable.java +++ b/core/java/android/nfc/technology/NdefFormatable.java @@ -91,11 +91,4 @@ public final class NdefFormatable extends BasicTagTechnology { Log.e(TAG, "NFC service dead", e); } } - - @Override - public byte[] transceive(byte[] data) { - checkConnected(); - - throw new UnsupportedOperationException(); - } } diff --git a/core/java/android/nfc/technology/NfcA.java b/core/java/android/nfc/technology/NfcA.java index 20fe09eb5187..0615a1042f95 100644 --- a/core/java/android/nfc/technology/NfcA.java +++ b/core/java/android/nfc/technology/NfcA.java @@ -21,6 +21,8 @@ import android.nfc.Tag; import android.os.Bundle; import android.os.RemoteException; +import java.io.IOException; + /** * A low-level connection to a {@link Tag} using the NFC-A technology, also known as * ISO1443-3A. @@ -44,6 +46,7 @@ public final class NfcA extends BasicTagTechnology { private short mSak; private byte[] mAtqa; + /** @hide */ public NfcA(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException { super(adapter, tag, TagTechnology.NFC_A); mSak = extras.getShort(EXTRA_SAK); @@ -63,4 +66,19 @@ public final class NfcA extends BasicTagTechnology { public short getSak() { return mSak; } + + /** + * Send data to a tag and receive the response. + * <p> + * This method will block until the response is received. It can be canceled + * with {@link #close}. + * <p>Requires {@link android.Manifest.permission#NFC} permission. + * + * @param data bytes to send + * @return bytes received in response + * @throws IOException if the target is lost or connection closed + */ + public byte[] transceive(byte[] data) throws IOException { + return transceive(data, true); + } } diff --git a/core/java/android/nfc/technology/NfcB.java b/core/java/android/nfc/technology/NfcB.java index 767558ebf8a4..c14b98dbc9bb 100644 --- a/core/java/android/nfc/technology/NfcB.java +++ b/core/java/android/nfc/technology/NfcB.java @@ -21,6 +21,8 @@ import android.nfc.Tag; import android.os.Bundle; import android.os.RemoteException; +import java.io.IOException; + /** * A low-level connection to a {@link Tag} using the NFC-B technology, also known as * ISO1443-3B. @@ -44,6 +46,7 @@ public final class NfcB extends BasicTagTechnology { private byte[] mAppData; private byte[] mProtInfo; + /** @hide */ public NfcB(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException { super(adapter, tag, TagTechnology.NFC_B); @@ -67,4 +70,18 @@ public final class NfcB extends BasicTagTechnology { return mProtInfo; } + /** + * Send data to a tag and receive the response. + * <p> + * This method will block until the response is received. It can be canceled + * with {@link #close}. + * <p>Requires {@link android.Manifest.permission#NFC} permission. + * + * @param data bytes to send + * @return bytes received in response + * @throws IOException if the target is lost or connection closed + */ + public byte[] transceive(byte[] data) throws IOException { + return transceive(data, true); + } } diff --git a/core/java/android/nfc/technology/NfcF.java b/core/java/android/nfc/technology/NfcF.java index f7f1fd3a9db7..434e5dfd590b 100644 --- a/core/java/android/nfc/technology/NfcF.java +++ b/core/java/android/nfc/technology/NfcF.java @@ -21,6 +21,8 @@ import android.nfc.Tag; import android.os.Bundle; import android.os.RemoteException; +import java.io.IOException; + /** * A low-level connection to a {@link Tag} using the NFC-F technology, also known as * JIS6319-4. @@ -44,6 +46,7 @@ public final class NfcF extends BasicTagTechnology { private byte[] mSystemCode = null; private byte[] mManufacturer = null; + /** @hide */ public NfcF(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException { super(adapter, tag, TagTechnology.NFC_F); @@ -60,4 +63,19 @@ public final class NfcF extends BasicTagTechnology { public byte[] getManufacturer() { return mManufacturer; } + + /** + * Send data to a tag and receive the response. + * <p> + * This method will block until the response is received. It can be canceled + * with {@link #close}. + * <p>Requires {@link android.Manifest.permission#NFC} permission. + * + * @param data bytes to send + * @return bytes received in response + * @throws IOException if the target is lost or connection closed + */ + public byte[] transceive(byte[] data) throws IOException { + return transceive(data, true); + } } diff --git a/core/java/android/nfc/technology/NfcV.java b/core/java/android/nfc/technology/NfcV.java index 4b51119b13e8..142ef9d12e0f 100644 --- a/core/java/android/nfc/technology/NfcV.java +++ b/core/java/android/nfc/technology/NfcV.java @@ -21,8 +21,10 @@ import android.nfc.Tag; import android.os.Bundle; import android.os.RemoteException; +import java.io.IOException; + /** - * A low-level connection to a {@link Tag} using the NFC-V technology, also known as + * A low-level connection to a {@link Tag} using NFC vicinity technology, also known as * ISO15693. * * <p>You can acquire this kind of connection with {@link NfcAdapter#getTechnology}. @@ -45,6 +47,7 @@ public final class NfcV extends BasicTagTechnology { private byte mRespFlags; private byte mDsfId; + /** @hide */ public NfcV(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException { super(adapter, tag, TagTechnology.NFC_V); @@ -59,4 +62,19 @@ public final class NfcV extends BasicTagTechnology { public byte getDsfId() { return mDsfId; } + + /** + * Send data to a tag and receive the response. + * <p> + * This method will block until the response is received. It can be canceled + * with {@link #close}. + * <p>Requires {@link android.Manifest.permission#NFC} permission. + * + * @param data bytes to send + * @return bytes received in response + * @throws IOException if the target is lost or connection closed + */ + public byte[] transceive(byte[] data) throws IOException { + return transceive(data, true); + } } diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java index 62216c1d7da1..96f1724ed075 100644 --- a/core/java/android/nfc/technology/TagTechnology.java +++ b/core/java/android/nfc/technology/TagTechnology.java @@ -22,47 +22,60 @@ import java.io.IOException; public interface TagTechnology { /** - * This object is an instance of {@link NfcA} + * This technology is an instance of {@link NfcA}. + * <p>Support for this technology type is mandatory. */ public static final int NFC_A = 1; /** - * This object is an instance of {@link NfcB} + * This technology is an instance of {@link NfcB}. + * <p>Support for this technology type is mandatory. */ public static final int NFC_B = 2; /** - * This object is an instance of {@link IsoDep} + * This technology is an instance of {@link IsoDep}. + * <p>Support for this technology type is mandatory. */ public static final int ISO_DEP = 3; /** - * This object is an instance of {@link NfcF} + * This technology is an instance of {@link NfcF}. + * <p>Support for this technology type is mandatory. */ public static final int NFC_F = 4; /** - * This object is an instance of {@link NfcV} + * This technology is an instance of {@link NfcV}. + * <p>Support for this technology type is mandatory. */ public static final int NFC_V = 5; /** - * This object is an instance of {@link Ndef} + * This technology is an instance of {@link Ndef}. + * <p>Support for this technology type is mandatory. */ public static final int NDEF = 6; /** - * This object is an instance of {@link NdefFormatable} + * This technology is an instance of {@link NdefFormatable}. + * <p>Support for this technology type is mandatory. */ public static final int NDEF_FORMATABLE = 7; /** - * This object is an instance of {@link MifareClassic} + * This technology is an instance of {@link MifareClassic}. + * <p>Support for this technology type is optional. If a stack doesn't support this technology + * type tags using it must still be discovered and present the lower level radio interface + * technologies in use. */ public static final int MIFARE_CLASSIC = 8; /** - * This object is an instance of {@link MifareUltralight} + * This technology is an instance of {@link MifareUltralight}. + * <p>Support for this technology type is optional. If a stack doesn't support this technology + * type tags using it must still be discovered and present the lower level radio interface + * technologies in use. */ public static final int MIFARE_ULTRALIGHT = 9; @@ -72,23 +85,51 @@ public interface TagTechnology { public int getTechnologyId(); /** - * Get the backing tag object. + * Get the {@link Tag} object this technology came from. */ public Tag getTag(); /** - * @throws IOException + * Opens a connection to the {@link Tag} enabling interactive commands. The command set + * varies by the technology type. + * + * <p>This method blocks until the connection has been established. + * + * <p>A call to {@link #close} from another thread will cancel a blocked call and cause an + * IOException to be thrown on the thread that is blocked. + * + * @see #reconnect() + * @see #close() + * @throws IOException if the target is lost, or connect canceled */ public void connect() throws IOException; /** + * Re-connect to the {@link Tag} associated with this connection. Reconnecting to a tag can be + * used to reset the state of the tag itself. + * + * <p>This method blocks until the connection is re-established. + * + * <p>A call to {@link #close} from another thread will cancel a blocked call and cause an + * IOException to be thrown on the thread that is blocked. + * + * @see #connect() + * @see #close() * @throws IOException */ public void reconnect() throws IOException; /** - * Non-blocking. Immediately causes all blocking calls - * to throw IOException. + * Closes the connection to the {@link Tag}. This call is non-blocking and causes all blocking + * operations such as {@link #connect} to be canceled and immediately throw + * {@link java.io.IOException} on the thread that is blocked. + * + * <p> + * Once this method is called, this object cannot be re-used and should be discarded. Further + * calls to {@link #connect} will fail. + * + * @see #connect() + * @see #reconnect() */ public void close(); } diff --git a/core/java/com/android/internal/widget/DigitalClock.java b/core/java/com/android/internal/widget/DigitalClock.java index fa47ff638cd5..303a1bfe077f 100644 --- a/core/java/com/android/internal/widget/DigitalClock.java +++ b/core/java/com/android/internal/widget/DigitalClock.java @@ -22,7 +22,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Typeface; import android.os.Handler; @@ -33,6 +32,7 @@ import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; +import java.lang.ref.WeakReference; import java.text.DateFormatSymbols; import java.util.Calendar; @@ -49,26 +49,41 @@ public class DigitalClock extends LinearLayout { private TextView mTimeDisplay; private AmPm mAmPm; private ContentObserver mFormatChangeObserver; - private boolean mLive = true; - private boolean mAttached; + private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced /* called by system on minute ticks */ private final Handler mHandler = new Handler(); - private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mLive && intent.getAction().equals( - Intent.ACTION_TIMEZONE_CHANGED)) { - mCalendar = Calendar.getInstance(); - } - // Post a runnable to avoid blocking the broadcast. - mHandler.post(new Runnable() { - public void run() { - updateTime(); + private BroadcastReceiver mIntentReceiver; + + private static class TimeChangedReceiver extends BroadcastReceiver { + private WeakReference<DigitalClock> mClock; + private Context mContext; + + public TimeChangedReceiver(DigitalClock clock) { + mClock = new WeakReference<DigitalClock>(clock); + mContext = clock.getContext(); + } + + @Override + public void onReceive(Context context, Intent intent) { + // Post a runnable to avoid blocking the broadcast. + final boolean timezoneChanged = + intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED); + final DigitalClock clock = mClock.get(); + if (clock != null) { + clock.mHandler.post(new Runnable() { + public void run() { + if (timezoneChanged) { + clock.mCalendar = Calendar.getInstance(); } + clock.updateTime(); + } }); + } else { + mContext.unregisterReceiver(this); } - }; + } + }; static class AmPm { private TextView mAmPm; @@ -94,14 +109,23 @@ public class DigitalClock extends LinearLayout { } } - private class FormatChangeObserver extends ContentObserver { - public FormatChangeObserver() { + private static class FormatChangeObserver extends ContentObserver { + private WeakReference<DigitalClock> mClock; + private Context mContext; + public FormatChangeObserver(DigitalClock clock) { super(new Handler()); + mClock = new WeakReference<DigitalClock>(clock); + mContext = clock.getContext(); } @Override public void onChange(boolean selfChange) { - setDateFormat(); - updateTime(); + DigitalClock digitalClock = mClock.get(); + if (digitalClock != null) { + digitalClock.setDateFormat(); + digitalClock.updateTime(); + } else { + mContext.getContentResolver().unregisterContentObserver(this); + } } } @@ -129,11 +153,11 @@ public class DigitalClock extends LinearLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); - if (mAttached) return; - mAttached = true; + mAttached++; - if (mLive) { - /* monitor time ticks, time changed, timezone */ + /* monitor time ticks, time changed, timezone */ + if (mIntentReceiver == null) { + mIntentReceiver = new TimeChangedReceiver(this); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); filter.addAction(Intent.ACTION_TIME_CHANGED); @@ -142,9 +166,11 @@ public class DigitalClock extends LinearLayout { } /* monitor 12/24-hour display preference */ - mFormatChangeObserver = new FormatChangeObserver(); - mContext.getContentResolver().registerContentObserver( - Settings.System.CONTENT_URI, true, mFormatChangeObserver); + if (mFormatChangeObserver == null) { + mFormatChangeObserver = new FormatChangeObserver(this); + mContext.getContentResolver().registerContentObserver( + Settings.System.CONTENT_URI, true, mFormatChangeObserver); + } updateTime(); } @@ -153,16 +179,19 @@ public class DigitalClock extends LinearLayout { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if (!mAttached) return; - mAttached = false; + mAttached--; - if (mLive) { + if (mIntentReceiver != null) { mContext.unregisterReceiver(mIntentReceiver); } - mContext.getContentResolver().unregisterContentObserver( - mFormatChangeObserver); - } + if (mFormatChangeObserver != null) { + mContext.getContentResolver().unregisterContentObserver( + mFormatChangeObserver); + } + mFormatChangeObserver = null; + mIntentReceiver = null; + } void updateTime(Calendar c) { mCalendar = c; @@ -170,9 +199,7 @@ public class DigitalClock extends LinearLayout { } private void updateTime() { - if (mLive) { - mCalendar.setTimeInMillis(System.currentTimeMillis()); - } + mCalendar.setTimeInMillis(System.currentTimeMillis()); CharSequence newTime = DateFormat.format(mFormat, mCalendar); mTimeDisplay.setText(newTime); @@ -180,12 +207,8 @@ public class DigitalClock extends LinearLayout { } private void setDateFormat() { - mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) + mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24 : M12; mAmPm.setShowAmPm(mFormat.equals(M12)); } - - void setLive(boolean live) { - mLive = live; - } } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 642a563fba7f..33cd8103b1e8 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -329,7 +329,14 @@ from the touch driver. This code exists for one particular device, and should not be enabled for any others. --> <bool name="config_filterJumpyTouchEvents">false</bool> - + + <!-- Specifies the amount of time to disable virtual keys after the screen is touched + in order to filter out accidental virtual key presses due to swiping gestures + or taps near the edge of the display. May be 0 to disable the feature. + It is recommended that this value be no more than 250 ms. + This feature should be disabled for most devices. --> + <integer name="config_virtualKeyQuietTimeMillis">0</integer> + <!-- Component name of the default wallpaper. This will be ImageWallpaper if not specified --> <string name="default_wallpaper_component">@null</string> diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index c8a4593b15bb..d5f385b290c4 100755 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -47,7 +47,6 @@ import android.util.Log; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; public class PackageManagerTests extends AndroidTestCase { private static final boolean localLOGV = true; @@ -2839,164 +2838,6 @@ public class PackageManagerTests extends AndroidTestCase { installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true, fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED); } - - @LargeTest - public void testPackageObbPaths_Nonexistent() { - try { - final PackageManager pm = getPm(); - - // Invalid Java package name. - pm.getPackageObbPaths("=non-existent"); - - fail("Should not be able to get package OBB paths for non-existent package"); - } catch (IllegalArgumentException e) { - // pass - } - } - - @LargeTest - public void testPackageObbPaths_Initial() { - InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); - - try { - final PackageManager pm = getPm(); - - assertEquals("Initial obb paths should be null", - null, pm.getPackageObbPaths(ip.pkg.packageName)); - } finally { - cleanUpInstall(ip); - } - } - - @LargeTest - public void testPackageObbPaths_Null() { - InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); - - try { - final PackageManager pm = getPm(); - - pm.setPackageObbPaths(ip.pkg.packageName, null); - - assertEquals("Returned paths should be null", - null, pm.getPackageObbPaths(ip.pkg.packageName)); - } finally { - cleanUpInstall(ip); - } - } - - @LargeTest - public void testPackageObbPaths_Empty() { - InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); - - try { - final PackageManager pm = getPm(); - - final String[] paths = new String[0]; - - pm.setPackageObbPaths(ip.pkg.packageName, paths); - - assertEquals("Empty list should be interpreted as null", - null, pm.getPackageObbPaths(ip.pkg.packageName)); - } finally { - cleanUpInstall(ip); - } - } - - @LargeTest - public void testPackageObbPaths_Single() { - InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); - - try { - final PackageManager pm = getPm(); - - final String[] paths = new String[] { - "/example/test", - }; - - pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); - - assertTrue("Previously set paths should be the same as the returned paths.", - Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); - } finally { - cleanUpInstall(ip); - } - } - - @LargeTest - public void testPackageObbPaths_Multiple() { - InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); - - try { - final PackageManager pm = getPm(); - - final String[] paths = new String[] { - "/example/test1", - "/example/test2", - }; - - pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); - - assertTrue("Previously set paths should be the same as the returned paths.", - Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); - } finally { - cleanUpInstall(ip); - } - } - - @LargeTest - public void testPackageObbPaths_Twice() { - InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); - - try { - final PackageManager pm = getPm(); - - final String[] paths = new String[] { - "/example/test1", - "/example/test2", - }; - - pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); - - assertTrue("Previously set paths should be the same as the returned paths.", - Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); - - paths[0] = "/example/test3"; - pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); - - assertTrue("Previously set paths should be the same as the returned paths.", - Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); - } finally { - cleanUpInstall(ip); - } - } - - @LargeTest - public void testPackageObbPaths_ReplacePackage() { - InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false); - - try { - final PackageManager pm = getPm(); - - final String[] paths = new String[] { - "/example/test1", - "/example/test2", - }; - - pm.setPackageObbPaths(ip.pkg.packageName, paths.clone()); - - Log.i(TAG, "Creating replaceReceiver"); - final GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName); - - final int flags = PackageManager.INSTALL_REPLACE_EXISTING; - invokeInstallPackage(ip.packageURI, flags, receiver); - assertInstall(ip.pkg, flags, ip.pkg.installLocation); - - assertTrue("Previously set paths should be the same as the returned paths.", - Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName))); - } finally { - cleanUpInstall(ip); - } - } /*---------- Recommended install location tests ----*/ /* * TODO's diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h index 49351b0ca5dc..7568ba72329a 100644 --- a/include/ui/InputReader.h +++ b/include/ui/InputReader.h @@ -103,6 +103,12 @@ public: */ virtual bool filterJumpyTouchEvents() = 0; + /* Gets the amount of time to disable virtual keys after the screen is touched + * in order to filter out accidental virtual key presses due to swiping gestures + * or taps near the edge of the display. May be 0 to disable the feature. + */ + virtual nsecs_t getVirtualKeyQuietTime() = 0; + /* Gets the configured virtual key definitions for an input device. */ virtual void getVirtualKeyDefinitions(const String8& deviceName, Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0; @@ -177,6 +183,10 @@ public: virtual void updateGlobalMetaState() = 0; virtual int32_t getGlobalMetaState() = 0; + virtual void disableVirtualKeysUntil(nsecs_t time) = 0; + virtual bool shouldDropVirtualKey(nsecs_t now, + InputDevice* device, int32_t keyCode, int32_t scanCode) = 0; + virtual InputReaderPolicyInterface* getPolicy() = 0; virtual InputDispatcherInterface* getDispatcher() = 0; virtual EventHubInterface* getEventHub() = 0; @@ -264,6 +274,11 @@ private: InputConfiguration mInputConfiguration; void updateInputConfiguration(); + nsecs_t mDisableVirtualKeysTimeout; + virtual void disableVirtualKeysUntil(nsecs_t time); + virtual bool shouldDropVirtualKey(nsecs_t now, + InputDevice* device, int32_t keyCode, int32_t scanCode); + // state queries typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code); int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code, @@ -585,6 +600,7 @@ protected: bool useBadTouchFilter; bool useJumpyTouchFilter; bool useAveragingTouchFilter; + nsecs_t virtualKeyQuietTime; } mParameters; // Immutable calibration parameters in parsed form. @@ -810,6 +826,7 @@ private: void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount, int32_t motionEventAction); + void detectGestures(nsecs_t when); bool isPointInsideSurfaceLocked(int32_t x, int32_t y); const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y); diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp index 969ee79853d2..a2a5455c4d31 100644 --- a/libs/surfaceflinger_client/ISurfaceComposer.cpp +++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp @@ -247,13 +247,13 @@ status_t BnSurfaceComposer::onTransact( int32_t mode = data.readInt32(); status_t res = turnElectronBeamOff(mode); reply->writeInt32(res); - } + } break; case TURN_ELECTRON_BEAM_ON: { CHECK_INTERFACE(ISurfaceComposer, data, reply); int32_t mode = data.readInt32(); status_t res = turnElectronBeamOn(mode); reply->writeInt32(res); - } + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp index 3197ab229ad7..83b382b9a7b0 100644 --- a/libs/ui/InputReader.cpp +++ b/libs/ui/InputReader.cpp @@ -198,7 +198,7 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputDispatcherInterface>& dispatcher) : mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher), - mGlobalMetaState(0) { + mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) { configureExcludedDevices(); updateGlobalMetaState(); updateInputConfiguration(); @@ -453,6 +453,24 @@ void InputReader::updateInputConfiguration() { } // release state lock } +void InputReader::disableVirtualKeysUntil(nsecs_t time) { + mDisableVirtualKeysTimeout = time; +} + +bool InputReader::shouldDropVirtualKey(nsecs_t now, + InputDevice* device, int32_t keyCode, int32_t scanCode) { + if (now < mDisableVirtualKeysTimeout) { + LOGI("Dropping virtual key from device %s because virtual keys are " + "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d", + device->getName().string(), + (mDisableVirtualKeysTimeout - now) * 0.000001, + keyCode, scanCode); + return true; + } else { + return false; + } +} + void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) { { // acquire state lock AutoMutex _l(mStateLock); @@ -937,6 +955,11 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode; } else { // key down + if ((policyFlags & POLICY_FLAG_VIRTUAL) + && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) { + return; + } + mLocked.keyDowns.push(); KeyDown& keyDown = mLocked.keyDowns.editTop(); keyDown.keyCode = keyCode; @@ -1340,6 +1363,7 @@ void TouchInputMapper::configureParameters() { mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents(); mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents(); mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents(); + mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime(); } void TouchInputMapper::dumpParameters(String8& dump) { @@ -2060,6 +2084,7 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { TouchResult touchResult = consumeOffScreenTouches(when, policyFlags); if (touchResult == DISPATCH_TOUCH) { + detectGestures(when); dispatchTouches(when, policyFlags); } @@ -2145,6 +2170,11 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( if (mCurrentTouch.pointerCount == 1) { const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y); if (virtualKey) { + if (mContext->shouldDropVirtualKey(when, getDevice(), + virtualKey->keyCode, virtualKey->scanCode)) { + return DROP_STROKE; + } + mLocked.currentVirtualKey.down = true; mLocked.currentVirtualKey.downTime = when; mLocked.currentVirtualKey.keyCode = virtualKey->keyCode; @@ -2182,6 +2212,26 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches( return touchResult; } +void TouchInputMapper::detectGestures(nsecs_t when) { + // Disable all virtual key touches that happen within a short time interval of the + // most recent touch. The idea is to filter out stray virtual key presses when + // interacting with the touch screen. + // + // Problems we're trying to solve: + // + // 1. While scrolling a list or dragging the window shade, the user swipes down into a + // virtual key area that is implemented by a separate touch panel and accidentally + // triggers a virtual key. + // + // 2. While typing in the on screen keyboard, the user taps slightly outside the screen + // area and accidentally triggers a virtual key. This often happens when virtual keys + // are layed out below the screen near to where the on screen keyboard's space bar + // is displayed. + if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) { + mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime); + } +} + void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) { uint32_t currentPointerCount = mCurrentTouch.pointerCount; uint32_t lastPointerCount = mLastTouch.pointerCount; diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp index de4b05ae3d3d..f31a6be0476c 100644 --- a/libs/ui/tests/InputReader_test.cpp +++ b/libs/ui/tests/InputReader_test.cpp @@ -131,6 +131,10 @@ private: return mFilterJumpyTouchEvents; } + virtual nsecs_t getVirtualKeyQuietTime() { + return 0; + } + virtual void getVirtualKeyDefinitions(const String8& deviceName, Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) { ssize_t index = mVirtualKeyDefinitions.indexOfKey(deviceName); @@ -631,6 +635,14 @@ private: virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } + + virtual void disableVirtualKeysUntil(nsecs_t time) { + } + + virtual bool shouldDropVirtualKey(nsecs_t now, + InputDevice* device, int32_t keyCode, int32_t scanCode) { + return false; + } }; diff --git a/native/android/looper.cpp b/native/android/looper.cpp index 9f5cda9a9e98..615493fe9a6c 100644 --- a/native/android/looper.cpp +++ b/native/android/looper.cpp @@ -19,9 +19,11 @@ #include <android/looper.h> #include <utils/Looper.h> +#include <binder/IPCThreadState.h> using android::Looper; using android::sp; +using android::IPCThreadState; ALooper* ALooper_forThread() { return Looper::getForThread().get(); @@ -46,6 +48,7 @@ int ALooper_pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outDa return ALOOPER_POLL_ERROR; } + IPCThreadState::self()->flushCommands(); return looper->pollOnce(timeoutMillis, outFd, outEvents, outData); } @@ -55,7 +58,8 @@ int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outDat LOGE("ALooper_pollAll: No looper for this thread!"); return ALOOPER_POLL_ERROR; } - + + IPCThreadState::self()->flushCommands(); return looper->pollAll(timeoutMillis, outFd, outEvents, outData); } diff --git a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java index 840c5e198e21..c4feefd2e32c 100644 --- a/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/AccountUnlockScreen.java @@ -62,8 +62,8 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree */ private static final int AWAKE_POKE_MILLIS = 30000; - private final KeyguardScreenCallback mCallback; - private final LockPatternUtils mLockPatternUtils; + private KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; private KeyguardUpdateMonitor mUpdateMonitor; private TextView mTopHeader; @@ -159,7 +159,10 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree if (mCheckingDialog != null) { mCheckingDialog.hide(); } - mUpdateMonitor.removeCallback(this); + mUpdateMonitor.removeCallback(this); // this must be first + mCallback = null; + mLockPatternUtils = null; + mUpdateMonitor = null; } /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java index ba1d7f530294..708e89d25264 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java @@ -223,8 +223,8 @@ public class KeyguardViewManager implements KeyguardWindowController { mKeyguardHost.postDelayed(new Runnable() { public void run() { synchronized (KeyguardViewManager.this) { - mKeyguardHost.removeView(lastView); lastView.cleanUp(); + mKeyguardHost.removeView(lastView); } } }, 500); diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 27706eff298d..f3d07ab82b91 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -495,8 +495,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase { public void cleanUp() { ((KeyguardScreen) mLockScreen).onPause(); ((KeyguardScreen) mLockScreen).cleanUp(); + this.removeView(mLockScreen); ((KeyguardScreen) mUnlockScreen).onPause(); ((KeyguardScreen) mUnlockScreen).cleanUp(); + this.removeView(mUnlockScreen); } private boolean isSecure() { diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index 635b7d308a35..5a20b9392e0c 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -55,9 +55,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM private Status mStatus = Status.Normal; - private final LockPatternUtils mLockPatternUtils; - private final KeyguardUpdateMonitor mUpdateMonitor; - private final KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; + private KeyguardUpdateMonitor mUpdateMonitor; + private KeyguardScreenCallback mCallback; private TextView mCarrier; private SlidingTab mSelector; @@ -225,8 +225,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM setFocusableInTouchMode(true); setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); - updateMonitor.registerInfoCallback(this); - updateMonitor.registerSimStateCallback(this); + mUpdateMonitor.registerInfoCallback(this); + mUpdateMonitor.registerSimStateCallback(this); mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); mSilentMode = isSilentMode(); @@ -668,7 +668,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM /** {@inheritDoc} */ public void cleanUp() { - mUpdateMonitor.removeCallback(this); + mUpdateMonitor.removeCallback(this); // this must be first + mLockPatternUtils = null; + mUpdateMonitor = null; + mCallback = null; } /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java index 418e24392279..ffd0a47418fd 100644 --- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java @@ -66,9 +66,9 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient private int mTotalFailedPatternAttempts = 0; private CountDownTimer mCountdownTimer = null; - private final LockPatternUtils mLockPatternUtils; - private final KeyguardUpdateMonitor mUpdateMonitor; - private final KeyguardScreenCallback mCallback; + private LockPatternUtils mLockPatternUtils; + private KeyguardUpdateMonitor mUpdateMonitor; + private KeyguardScreenCallback mCallback; /** * whether there is a fallback option available when the pattern is forgotten. @@ -478,6 +478,9 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient /** {@inheritDoc} */ public void cleanUp() { mUpdateMonitor.removeCallback(this); + mLockPatternUtils = null; + mUpdateMonitor = null; + mCallback = null; } @Override diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java index b44fe0038de8..ba39c577d610 100644 --- a/services/java/com/android/server/InputManager.java +++ b/services/java/com/android/server/InputManager.java @@ -411,7 +411,13 @@ public class InputManager { return mContext.getResources().getBoolean( com.android.internal.R.bool.config_filterJumpyTouchEvents); } - + + @SuppressWarnings("unused") + public int getVirtualKeyQuietTimeMillis() { + return mContext.getResources().getInteger( + com.android.internal.R.integer.config_virtualKeyQuietTimeMillis); + } + @SuppressWarnings("unused") public VirtualKeyDefinition[] getVirtualKeyDefinitions(String deviceName) { ArrayList<VirtualKeyDefinition> keys = new ArrayList<VirtualKeyDefinition>(); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 39c754071654..9b8a6057743e 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -102,7 +102,6 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; -import java.lang.reflect.Array; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -4396,8 +4395,6 @@ class PackageManagerService extends IPackageManager.Stub { } }; - private static final boolean DEBUG_OBB = false; - private static final void sendPackageBroadcast(String action, String pkg, Bundle extras, IIntentReceiver finishedReceiver) { IActivityManager am = ActivityManagerNative.getDefault(); @@ -4573,64 +4570,6 @@ class PackageManagerService extends IPackageManager.Stub { mHandler.sendMessage(msg); } - public void setPackageObbPaths(String packageName, String[] paths) { - if (DEBUG_OBB) - Log.v(TAG, "Setting .obb paths for " + packageName + " to: " + Arrays.toString(paths)); - final int uid = Binder.getCallingUid(); - final int permission = mContext.checkCallingPermission( - android.Manifest.permission.INSTALL_PACKAGES); - final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); - if (!allowedByPermission) { - throw new SecurityException("Permission denial: attempt to set .obb file from pid=" - + Binder.getCallingPid()); - } - synchronized (mPackages) { - final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); - if (pkgSetting == null) { - throw new IllegalArgumentException("Unknown package: " + packageName); - } - - if (paths != null) { - if (paths.length == 0) { - // Don't bother storing an empty array. - paths = null; - } else { - // Don't allow the caller to manipulate our copy of the - // list. - paths = paths.clone(); - } - } - - // Only write settings file if the new and old settings are not the - // same. - if (!Arrays.equals(paths, pkgSetting.obbPathStrings)) { - pkgSetting.obbPathStrings = paths; - mSettings.writeLP(); - } - } - } - - public String[] getPackageObbPaths(String packageName) { - if (DEBUG_OBB) - Log.v(TAG, "Getting .obb paths for " + packageName); - final int uid = Binder.getCallingUid(); - final int permission = mContext.checkCallingPermission( - android.Manifest.permission.INSTALL_PACKAGES); - final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); - synchronized (mPackages) { - final PackageSetting pkgSetting = mSettings.mPackages.get(packageName); - if (pkgSetting == null) { - throw new IllegalArgumentException("Unknown package: " + packageName); - } - if (!allowedByPermission && (uid != pkgSetting.userId)) { - throw new SecurityException("Permission denial: attempt to set .obb file from pid=" - + Binder.getCallingPid() + ", uid=" + uid + ", package uid=" - + pkgSetting.userId); - } - return pkgSetting.obbPathStrings; - } - } - private void processPendingInstall(final InstallArgs args, final int currentStatus) { // Queue up an async operation since the package installation may take a little while. mHandler.post(new Runnable() { @@ -7200,7 +7139,6 @@ class PackageManagerService extends IPackageManager.Stub { pw.print(" codePath="); pw.println(ps.codePathString); pw.print(" resourcePath="); pw.println(ps.resourcePathString); pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString); - pw.print(" obbPaths="); pw.println(Arrays.toString(ps.obbPathStrings)); pw.print(" versionCode="); pw.println(ps.versionCode); if (ps.pkg != null) { pw.print(" versionName="); pw.println(ps.pkg.mVersionName); @@ -7778,7 +7716,6 @@ class PackageManagerService extends IPackageManager.Stub { File resourcePath; String resourcePathString; String nativeLibraryPathString; - String[] obbPathStrings; long timeStamp; long firstInstallTime; long lastUpdateTime; @@ -7824,11 +7761,6 @@ class PackageManagerService extends IPackageManager.Stub { resourcePath = base.resourcePath; resourcePathString = base.resourcePathString; nativeLibraryPathString = base.nativeLibraryPathString; - - if (base.obbPathStrings != null) { - obbPathStrings = base.obbPathStrings.clone(); - } - timeStamp = base.timeStamp; firstInstallTime = base.firstInstallTime; lastUpdateTime = base.lastUpdateTime; @@ -8887,16 +8819,6 @@ class PackageManagerService extends IPackageManager.Stub { if (pkg.installerPackageName != null) { serializer.attribute(null, "installer", pkg.installerPackageName); } - if (pkg.obbPathStrings != null && pkg.obbPathStrings.length > 0) { - int N = pkg.obbPathStrings.length; - serializer.startTag(null, "obbs"); - for (int i = 0; i < N; i++) { - serializer.startTag(null, "obb"); - serializer.attribute(null, "path", pkg.obbPathStrings[i]); - serializer.endTag(null, "obb"); - } - serializer.endTag(null, "obbs"); - } pkg.signatures.writeXml(serializer, "sigs", mPastSignatures); if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { serializer.startTag(null, "perms"); @@ -9489,8 +9411,6 @@ class PackageManagerService extends IPackageManager.Stub { readGrantedPermissionsLP(parser, packageSetting.grantedPermissions); packageSetting.permissionsFixed = true; - } else if (tagName.equals("obbs")) { - readObbPathsLP(packageSetting, parser); } else { reportSettingsProblem(Log.WARN, "Unknown element under <package>: " @@ -9695,34 +9615,6 @@ class PackageManagerService extends IPackageManager.Stub { } } - private void readObbPathsLP(PackageSettingBase packageSetting, XmlPullParser parser) - throws XmlPullParserException, IOException { - final List<String> obbPaths = new ArrayList<String>(); - final int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - final String tagName = parser.getName(); - if (tagName.equals("obb")) { - final String path = parser.getAttributeValue(null, "path"); - obbPaths.add(path); - } else { - reportSettingsProblem(Log.WARN, "Unknown element under <obbs>: " - + parser.getName()); - } - XmlUtils.skipCurrentTag(parser); - } - if (obbPaths.size() == 0) { - return; - } else { - packageSetting.obbPathStrings = obbPaths.toArray(new String[obbPaths.size()]); - } - } - // Returns -1 if we could not find an available UserId to assign private int newUserIdLP(Object obj) { // Let's be stupidly inefficient for now... diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 693d630be7d9..171471e264af 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -55,6 +55,7 @@ static struct { jmethodID checkInjectEventsPermission; jmethodID filterTouchEvents; jmethodID filterJumpyTouchEvents; + jmethodID getVirtualKeyQuietTimeMillis; jmethodID getVirtualKeyDefinitions; jmethodID getInputDeviceCalibration; jmethodID getExcludedDeviceNames; @@ -183,6 +184,7 @@ public: int32_t* width, int32_t* height, int32_t* orientation); virtual bool filterTouchEvents(); virtual bool filterJumpyTouchEvents(); + virtual nsecs_t getVirtualKeyQuietTime(); virtual void getVirtualKeyDefinitions(const String8& deviceName, Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions); virtual void getInputDeviceCalibration(const String8& deviceName, @@ -233,6 +235,7 @@ private: // Cached filtering policies. int32_t mFilterTouchEvents; int32_t mFilterJumpyTouchEvents; + nsecs_t mVirtualKeyQuietTime; // Cached throttling policy. int32_t mMaxEventsPerSecond; @@ -264,7 +267,7 @@ private: // ---------------------------------------------------------------------------- NativeInputManager::NativeInputManager(jobject callbacksObj) : - mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), + mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1), mMaxEventsPerSecond(-1), mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0) { JNIEnv* env = jniEnv(); @@ -451,6 +454,24 @@ bool NativeInputManager::filterJumpyTouchEvents() { return mFilterJumpyTouchEvents; } +nsecs_t NativeInputManager::getVirtualKeyQuietTime() { + if (mVirtualKeyQuietTime < 0) { + JNIEnv* env = jniEnv(); + + jint result = env->CallIntMethod(mCallbacksObj, + gCallbacksClassInfo.getVirtualKeyQuietTimeMillis); + if (checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) { + result = 0; + } + if (result < 0) { + result = 0; + } + + mVirtualKeyQuietTime = milliseconds_to_nanoseconds(result); + } + return mVirtualKeyQuietTime; +} + void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName, Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) { outVirtualKeyDefinitions.clear(); @@ -1351,6 +1372,9 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gCallbacksClassInfo.filterJumpyTouchEvents, gCallbacksClassInfo.clazz, "filterJumpyTouchEvents", "()Z"); + GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyQuietTimeMillis, gCallbacksClassInfo.clazz, + "getVirtualKeyQuietTimeMillis", "()I"); + GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyDefinitions, gCallbacksClassInfo.clazz, "getVirtualKeyDefinitions", "(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;"); diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 4a18b3e3afa0..c5d45f5c2914 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -489,18 +489,4 @@ public class MockPackageManager extends PackageManager { public boolean isSafeMode() { throw new UnsupportedOperationException(); } - - public void setPackageObbPath(String packageName, String path) { - throw new UnsupportedOperationException(); - } - - @Override - public void setPackageObbPaths(String packageName, String[] paths) { - throw new UnsupportedOperationException(); - } - - @Override - public String[] getPackageObbPaths(String packageName) { - throw new UnsupportedOperationException(); - } } |