Enforce foreground NDEF push.
Store the calling UID along with the NDEF callback,
to make sure the registered callback is running in
the foreground.
Bug: 5199662
Change-Id: Ia6eb4457309445909629878f3371805a503fc82f
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 3b41efd..2791307 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -382,6 +382,7 @@
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_PRESENT);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
registerForAirplaneMode(filter);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
@@ -869,7 +870,7 @@
@Override
public void setNdefPushCallback(INdefPushCallback callback) {
mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
- mP2pLinkManager.setNdefCallback(callback);
+ mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid());
}
@Override
@@ -2025,6 +2026,8 @@
} else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
new EnableDisableTask().execute(TASK_ENABLE);
}
+ } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
+ mP2pLinkManager.onUserSwitched();
}
}
};
diff --git a/src/com/android/nfc/P2pLinkManager.java b/src/com/android/nfc/P2pLinkManager.java
index 9b23f65..317c866 100755
--- a/src/com/android/nfc/P2pLinkManager.java
+++ b/src/com/android/nfc/P2pLinkManager.java
@@ -38,13 +38,11 @@
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.os.AsyncTask;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Profile;
+import android.os.UserHandle;
import android.util.Log;
import java.io.FileDescriptor;
@@ -152,16 +150,11 @@
static final int SNEP_FAILURE = 1;
static final int SNEP_HANDOVER_UNSUPPORTED = 2;
- static final Uri PROFILE_URI = Profile.CONTENT_VCARD_URI.buildUpon().
- appendQueryParameter(Contacts.QUERY_PARAMETER_VCARD_NO_PHOTO, "true").
- build();
-
final NdefPushServer mNdefPushServer;
final SnepServer mDefaultSnepServer;
final HandoverServer mHandoverServer;
final EchoServer mEchoServer;
final ActivityManager mActivityManager;
- final PackageManager mPackageManager;
final Context mContext;
final P2pEventListener mEventListener;
final Handler mHandler;
@@ -171,6 +164,7 @@
final int mDefaultRwSize;
// Locked on NdefP2pManager.this
+ PackageManager mPackageManager;
int mLinkState;
int mSendState; // valid during LINK_STATE_UP or LINK_STATE_DEBOUNCE
boolean mIsSendEnabled;
@@ -178,6 +172,7 @@
NdefMessage mMessageToSend; // valid during SEND_STATE_NEED_CONFIRMATION or SEND_STATE_SENDING
Uri[] mUrisToSend; // valid during SEND_STATE_NEED_CONFIRMATION or SEND_STATE_SENDING
INdefPushCallback mCallbackNdef;
+ String[] mValidCallbackPackages;
SendTask mSendTask;
SharedPreferences mPrefs;
boolean mFirstBeam;
@@ -242,9 +237,10 @@
* currently off or P2P send is currently off). They will become
* active as soon as P2P send is enabled.
*/
- public void setNdefCallback(INdefPushCallback callbackNdef) {
+ public void setNdefCallback(INdefPushCallback callbackNdef, int callingUid) {
synchronized (this) {
mCallbackNdef = callbackNdef;
+ mValidCallbackPackages = mPackageManager.getPackagesForUid(callingUid);
}
}
@@ -290,6 +286,18 @@
}
}
+ public void onUserSwitched() {
+ // Update the cached package manager in case of user switch
+ synchronized (P2pLinkManager.this) {
+ try {
+ mPackageManager = mContext.createPackageContextAsUser("android", 0,
+ new UserHandle(ActivityManager.getCurrentUser())).getPackageManager();
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Failed to retrieve PackageManager for user");
+ }
+ }
+ }
+
void prepareMessageToSend() {
synchronized (P2pLinkManager.this) {
if (!mIsSendEnabled) {
@@ -298,32 +306,61 @@
return;
}
+ String runningPackage = null;
+ List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
+ if (tasks.size() > 0) {
+ runningPackage = tasks.get(0).baseActivity.getPackageName();
+ }
+
+ if (runningPackage == null) {
+ Log.e(TAG, "Could not determine running package.");
+ mMessageToSend = null;
+ mUrisToSend = null;
+ return;
+ }
+
// Try application callback first
- //TODO: Check that mCallbackNdef refers to the foreground activity
if (mCallbackNdef != null) {
- try {
- mMessageToSend = mCallbackNdef.createMessage();
- mUrisToSend = mCallbackNdef.getUris();
- return;
- } catch (RemoteException e) {
- // Ignore
+ // Check to see if the package currently running
+ // is the one that registered any callbacks
+ boolean callbackValid = false;
+
+ if (mValidCallbackPackages != null) {
+ for (String pkg : mValidCallbackPackages) {
+ if (pkg.equals(runningPackage)) {
+ callbackValid = true;
+ break;
+ }
+ }
+ }
+
+ if (callbackValid) {
+ try {
+ mMessageToSend = mCallbackNdef.createMessage();
+ mUrisToSend = mCallbackNdef.getUris();
+ return;
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ } else {
+ // This is not necessarily an error - we no longer unset callbacks from
+ // the app process itself (to prevent IPC calls on every pause).
+ // Hence it may simply be a stale callback.
+ if (DBG) Log.d(TAG, "Last registered callback is not running in the foreground.");
}
}
- // fall back to default NDEF for this activity, unless the
+ // fall back to default NDEF for the foreground activity, unless the
// application disabled this explicitly in their manifest.
- List<RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
- if (tasks.size() > 0) {
- String pkg = tasks.get(0).baseActivity.getPackageName();
- if (beamDefaultDisabled(pkg)) {
- Log.d(TAG, "Disabling default Beam behavior");
- mMessageToSend = null;
- } else {
- mMessageToSend = createDefaultNdef(pkg);
- }
- } else {
+ if (beamDefaultDisabled(runningPackage)) {
+ Log.d(TAG, "Disabling default Beam behavior");
mMessageToSend = null;
+ mUrisToSend = null;
+ } else {
+ mMessageToSend = createDefaultNdef(runningPackage);
+ mUrisToSend = null;
}
+
if (DBG) Log.d(TAG, "mMessageToSend = " + mMessageToSend);
if (DBG) Log.d(TAG, "mUrisToSend = " + mUrisToSend);
}