summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xAndroidManifest.xml5
-rwxr-xr-xnci/jni/NativeNfcTag.cpp26
-rwxr-xr-xnci/src/com/android/nfc/dhimpl/NativeNfcManager.java14
-rw-r--r--src/com/android/nfc/NfcApplication.java24
-rw-r--r--src/com/android/nfc/NfcDispatcher.java37
-rw-r--r--src/com/android/nfc/NfcRootActivity.java4
-rwxr-xr-xsrc/com/android/nfc/NfcService.java143
-rw-r--r--src/com/android/nfc/RegisteredComponentCache.java31
-rw-r--r--src/com/android/nfc/handover/BluetoothHeadsetHandover.java8
-rw-r--r--src/com/android/nfc/handover/HandoverManager.java10
10 files changed, 193 insertions, 109 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f0c027f..3157598 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,10 +20,11 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="com.android.permission.WHITELIST_BLUETOOTH_DEVICE" />
<uses-permission android:name="com.android.permission.HANDOVER_STATUS" />
-
- <application android:name=".NfcService"
+ <application android:name=".NfcApplication"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:persistent="true"
diff --git a/nci/jni/NativeNfcTag.cpp b/nci/jni/NativeNfcTag.cpp
index 8c0426b..0ba7b21 100755
--- a/nci/jni/NativeNfcTag.cpp
+++ b/nci/jni/NativeNfcTag.cpp
@@ -806,6 +806,7 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da
bool fNeedToSwitchBack = false;
nfc_jni_native_data *nat = getNative (0, 0);
bool waitOk = false;
+ bool isNack = false;
uint8_t *buf = NULL;
uint32_t bufLen = 0;
jint *targetLost = NULL;
@@ -884,24 +885,21 @@ static jbyteArray nativeNfcTag_doTransceive (JNIEnv *e, jobject o, jbyteArray da
if ((natTag.getProtocol () == NFA_PROTOCOL_T2T) &&
natTag.isT2tNackResponse (sTransceiveData, sTransceiveDataLen))
{
- if (targetLost)
- {
- ALOGD ("%s: t2t nack", __FUNCTION__);
- *targetLost = 1; //causes NFC service to throw TagLostException
- }
- break;
+ isNack = true;
}
if (sTransceiveDataLen)
{
- // marshall data to java for return
- result = e->NewByteArray (sTransceiveDataLen);
- if (result != NULL)
- {
- e->SetByteArrayRegion (result, 0, sTransceiveDataLen, (jbyte *) sTransceiveData);
- }
- else
- ALOGE ("%s: Failed to allocate java byte array", __FUNCTION__);
+ if (!isNack) {
+ // marshall data to java for return
+ result = e->NewByteArray (sTransceiveDataLen);
+ if (result != NULL)
+ {
+ e->SetByteArrayRegion (result, 0, sTransceiveDataLen, (jbyte *) sTransceiveData);
+ }
+ else
+ ALOGE ("%s: Failed to allocate java byte array", __FUNCTION__);
+ } // else a nack is treated as a transceive failure to the upper layers
free (sTransceiveData);
sTransceiveData = NULL;
diff --git a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
index dde0c08..cc485a5 100755
--- a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
+++ b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
@@ -40,6 +40,18 @@ public class NativeNfcManager implements DeviceHost {
static final String DRIVER_NAME = "android-nci";
+ private static final byte[][] EE_WIPE_APDUS = {
+ {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
+ {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00,
+ (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00},
+ {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
+ {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
+ {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00,
+ (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00},
+ {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
+ {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
+ };
+
static {
System.loadLibrary("nfc_nci_jni");
}
@@ -281,7 +293,7 @@ public class NativeNfcManager implements DeviceHost {
@Override
public byte[][] getWipeApdus() {
- return null;
+ return EE_WIPE_APDUS;
}
@Override
diff --git a/src/com/android/nfc/NfcApplication.java b/src/com/android/nfc/NfcApplication.java
new file mode 100644
index 0000000..867b8bb
--- /dev/null
+++ b/src/com/android/nfc/NfcApplication.java
@@ -0,0 +1,24 @@
+package com.android.nfc;
+
+import android.app.Application;
+import android.os.UserHandle;
+import android.util.Log;
+
+public class NfcApplication extends Application {
+
+ public static final String TAG = "NfcApplication";
+ NfcService mNfcService;
+
+ public NfcApplication() {
+
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ if (UserHandle.myUserId() == 0) {
+ mNfcService = new NfcService(this);
+ }
+ }
+}
diff --git a/src/com/android/nfc/NfcDispatcher.java b/src/com/android/nfc/NfcDispatcher.java
index f628dea..1721d1a 100644
--- a/src/com/android/nfc/NfcDispatcher.java
+++ b/src/com/android/nfc/NfcDispatcher.java
@@ -20,6 +20,7 @@ import com.android.nfc.RegisteredComponentCache.ComponentInfo;
import com.android.nfc.handover.HandoverManager;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.PendingIntent;
@@ -30,6 +31,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.nfc.NdefMessage;
@@ -38,6 +40,7 @@ import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import java.io.FileDescriptor;
@@ -58,7 +61,6 @@ public class NfcDispatcher {
final Context mContext;
final IActivityManager mIActivityManager;
final RegisteredComponentCache mTechListFilters;
- final PackageManager mPackageManager;
final ContentResolver mContentResolver;
final HandoverManager mHandoverManager;
@@ -72,7 +74,6 @@ public class NfcDispatcher {
mIActivityManager = ActivityManagerNative.getDefault();
mTechListFilters = new RegisteredComponentCache(mContext,
NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED);
- mPackageManager = context.getPackageManager();
mContentResolver = context.getContentResolver();
mHandoverManager = handoverManager;
}
@@ -157,19 +158,21 @@ public class NfcDispatcher {
// is not available on Context. Instead, we query the PackageManager beforehand
// to determine if there is an Activity to handle this intent, and base the
// result of off that.
- List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
+ List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(intent, 0,
+ ActivityManager.getCurrentUser());
if (activities.size() > 0) {
- context.startActivity(rootIntent);
+ context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
return true;
}
return false;
}
boolean tryStartActivity(Intent intentToStart) {
- List<ResolveInfo> activities = packageManager.queryIntentActivities(intentToStart, 0);
+ List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(
+ intentToStart, 0, ActivityManager.getCurrentUser());
if (activities.size() > 0) {
rootIntent.putExtra(NfcRootActivity.EXTRA_LAUNCH_INTENT, intentToStart);
- context.startActivity(rootIntent);
+ context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
return true;
}
return false;
@@ -323,7 +326,16 @@ public class NfcDispatcher {
// Try to perform regular launch of the first AAR
if (aarPackages.size() > 0) {
String firstPackage = aarPackages.get(0);
- Intent appLaunchIntent = mPackageManager.getLaunchIntentForPackage(firstPackage);
+ PackageManager pm;
+ try {
+ UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
+ pm = mContext.createPackageContextAsUser("android", 0,
+ currentUser).getPackageManager();
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not create user package context");
+ return false;
+ }
+ Intent appLaunchIntent = pm.getLaunchIntentForPackage(firstPackage);
if (appLaunchIntent != null && dispatch.tryStartActivity(appLaunchIntent)) {
if (DBG) Log.i(TAG, "matched AAR to application launch");
return true;
@@ -367,11 +379,20 @@ public class NfcDispatcher {
ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
List<ComponentInfo> registered = mTechListFilters.getComponents();
+ PackageManager pm;
+ try {
+ UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
+ pm = mContext.createPackageContextAsUser("android", 0,
+ currentUser).getPackageManager();
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not create user package context");
+ return false;
+ }
// Check each registered activity to see if it matches
for (ComponentInfo info : registered) {
// Don't allow wild card matching
if (filterMatch(tagTechs, info.techs) &&
- isComponentEnabled(mPackageManager, info.resolveInfo)) {
+ isComponentEnabled(pm, info.resolveInfo)) {
// Add the activity as a match if it's not already in the list
if (!matches.contains(info.resolveInfo)) {
matches.add(info.resolveInfo);
diff --git a/src/com/android/nfc/NfcRootActivity.java b/src/com/android/nfc/NfcRootActivity.java
index 1325ead..cc216f2 100644
--- a/src/com/android/nfc/NfcRootActivity.java
+++ b/src/com/android/nfc/NfcRootActivity.java
@@ -17,9 +17,11 @@
package com.android.nfc;
import android.app.Activity;
+import android.app.ActivityManager;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
+import android.os.UserHandle;
public class NfcRootActivity extends Activity {
@@ -33,7 +35,7 @@ public class NfcRootActivity extends Activity {
final Intent launchIntent = intent.getParcelableExtra(EXTRA_LAUNCH_INTENT);
if (launchIntent != null) {
try {
- startActivity(launchIntent);
+ startActivityAsUser(launchIntent, UserHandle.CURRENT);
} catch (ActivityNotFoundException e) {
}
}
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 519c15b..c344b49 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -63,6 +63,7 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -75,7 +76,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ExecutionException;
-public class NfcService extends Application implements DeviceHostListener {
+public class NfcService implements DeviceHostListener {
private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
static final boolean DBG = false;
@@ -169,6 +170,8 @@ public class NfcService extends Application implements DeviceHostListener {
// fields below are used in multiple threads and protected by synchronized(this)
final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
+ // mSePackages holds packages that accessed the SE, but only for the owner user,
+ // as SE access is not granted for non-owner users.
HashSet<String> mSePackages = new HashSet<String>();
int mScreenState;
boolean mIsNdefPushEnabled;
@@ -220,6 +223,9 @@ public class NfcService extends Application implements DeviceHostListener {
throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH +
" denies NFCEE access to " + pkg);
}
+ if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ throw new SecurityException("only the owner is allowed to call SE APIs");
+ }
}
public static NfcService getInstance() {
@@ -288,10 +294,7 @@ public class NfcService extends Application implements DeviceHostListener {
sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block);
}
- @Override
- public void onCreate() {
- super.onCreate();
-
+ public NfcService(Application nfcApplication) {
mNfcTagService = new TagService();
mNfcAdapter = new NfcAdapterService();
mExtrasService = new NfcAdapterExtrasService();
@@ -300,11 +303,11 @@ public class NfcService extends Application implements DeviceHostListener {
sService = this;
- mContext = this;
- mDeviceHost = new NativeNfcManager(this, this);
+ mContext = nfcApplication;
+ mDeviceHost = new NativeNfcManager(mContext, this);
HandoverManager handoverManager = new HandoverManager(mContext);
- mNfcDispatcher = new NfcDispatcher(this, handoverManager);
+ mNfcDispatcher = new NfcDispatcher(mContext, handoverManager);
mP2pLinkManager = new P2pLinkManager(mContext, handoverManager,
mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
@@ -312,42 +315,48 @@ public class NfcService extends Application implements DeviceHostListener {
mSecureElement = new NativeNfcSecureElement(mContext);
mEeRoutingState = ROUTE_OFF;
- mNfceeAccessControl = new NfceeAccessControl(this);
+ mNfceeAccessControl = new NfceeAccessControl(mContext);
- mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE);
+ mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
mPrefsEditor = mPrefs.edit();
mState = NfcAdapter.STATE_OFF;
mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
- mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mRoutingWakeLock = mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
mEeWakeLock = mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock");
- mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+ mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mScreenState = checkScreenState();
ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
+ // Intents only for owner
+ IntentFilter ownerFilter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
+ ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+ ownerFilter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
+
+ mContext.registerReceiver(mOwnerReceiver, ownerFilter);
+
+ ownerFilter = new IntentFilter();
+ ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ ownerFilter.addDataScheme("package");
+
+ mContext.registerReceiver(mOwnerReceiver, ownerFilter);
+
+ // Intents for all users
IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
filter.addAction(Intent.ACTION_USER_PRESENT);
- filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
- filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
registerForAirplaneMode(filter);
- registerReceiver(mReceiver, filter);
-
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
-
- registerReceiver(mReceiver, filter);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
updatePackageCache();
@@ -358,9 +367,9 @@ public class NfcService extends Application implements DeviceHostListener {
synchronized(this) {
if (mSoundPool == null) {
mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
- mStartSound = mSoundPool.load(this, R.raw.start, 1);
- mEndSound = mSoundPool.load(this, R.raw.end, 1);
- mErrorSound = mSoundPool.load(this, R.raw.error, 1);
+ mStartSound = mSoundPool.load(mContext, R.raw.start, 1);
+ mEndSound = mSoundPool.load(mContext, R.raw.end, 1);
+ mErrorSound = mSoundPool.load(mContext, R.raw.error, 1);
}
}
}
@@ -392,8 +401,8 @@ public class NfcService extends Application implements DeviceHostListener {
}
void updatePackageCache() {
- PackageManager pm = getPackageManager();
- List<PackageInfo> packages = pm.getInstalledPackages(0);
+ PackageManager pm = mContext.getPackageManager();
+ List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER);
synchronized (this) {
mInstalledPackages = packages;
}
@@ -667,7 +676,7 @@ public class NfcService extends Application implements DeviceHostListener {
Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState);
- mContext.sendBroadcast(intent);
+ mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
}
}
@@ -699,12 +708,6 @@ public class NfcService extends Application implements DeviceHostListener {
}
}
- @Override
- public void onTerminate() {
- super.onTerminate();
- // NFC application is persistent, it should not be destroyed by framework
- Log.wtf(TAG, "NFC service is under attack!");
- }
final class NfcAdapterService extends INfcAdapter.Stub {
@Override
@@ -1291,7 +1294,7 @@ public class NfcService extends Application implements DeviceHostListener {
// Add the calling package to the list of packages that have accessed
// the secure element.
- for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) {
+ for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) {
mSePackages.add(packageName);
}
}
@@ -1861,39 +1864,11 @@ public class NfcService extends Application implements DeviceHostListener {
}
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (action.equals(
- NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
- // Perform applyRouting() in AsyncTask to serialize blocking calls
- new ApplyRoutingTask().execute();
- } else if (action.equals(Intent.ACTION_SCREEN_ON)
- || action.equals(Intent.ACTION_SCREEN_OFF)
- || action.equals(Intent.ACTION_USER_PRESENT)) {
- // Perform applyRouting() in AsyncTask to serialize blocking calls
- int screenState = SCREEN_STATE_OFF;
- if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- screenState = SCREEN_STATE_OFF;
- } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
- screenState = mKeyguard.isKeyguardLocked() ?
- SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED;
- } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
- screenState = SCREEN_STATE_ON_UNLOCKED;
- }
- new ApplyRoutingTask().execute(Integer.valueOf(screenState));
- } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
- EnableDisableTask eeWipeTask = new EnableDisableTask();
- eeWipeTask.execute(TASK_EE_WIPE);
- try {
- eeWipeTask.get(); // blocks until EE wipe is complete
- } catch (ExecutionException e) {
- Log.w(TAG, "failed to wipe NFC-EE");
- } catch (InterruptedException e) {
- Log.w(TAG, "failed to wipe NFC-EE");
- }
- } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
+ if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
action.equals(Intent.ACTION_PACKAGE_ADDED) ||
action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) ||
action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
@@ -1917,6 +1892,42 @@ public class NfcService extends Application implements DeviceHostListener {
}
}
}
+ } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
+ EnableDisableTask eeWipeTask = new EnableDisableTask();
+ eeWipeTask.execute(TASK_EE_WIPE);
+ try {
+ eeWipeTask.get(); // blocks until EE wipe is complete
+ } catch (ExecutionException e) {
+ Log.w(TAG, "failed to wipe NFC-EE");
+ } catch (InterruptedException e) {
+ Log.w(TAG, "failed to wipe NFC-EE");
+ }
+ }
+ }
+ };
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(
+ NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
+ // Perform applyRouting() in AsyncTask to serialize blocking calls
+ new ApplyRoutingTask().execute();
+ } else if (action.equals(Intent.ACTION_SCREEN_ON)
+ || action.equals(Intent.ACTION_SCREEN_OFF)
+ || action.equals(Intent.ACTION_USER_PRESENT)) {
+ // Perform applyRouting() in AsyncTask to serialize blocking calls
+ int screenState = SCREEN_STATE_OFF;
+ if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ screenState = SCREEN_STATE_OFF;
+ } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ screenState = mKeyguard.isKeyguardLocked() ?
+ SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED;
+ } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
+ screenState = SCREEN_STATE_ON_UNLOCKED;
+ }
+ new ApplyRoutingTask().execute(Integer.valueOf(screenState));
} else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
// Query the airplane mode from Settings.System just to make sure that
diff --git a/src/com/android/nfc/RegisteredComponentCache.java b/src/com/android/nfc/RegisteredComponentCache.java
index 1bac283..5da2cd4 100644
--- a/src/com/android/nfc/RegisteredComponentCache.java
+++ b/src/com/android/nfc/RegisteredComponentCache.java
@@ -19,6 +19,7 @@ package com.android.nfc;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -29,6 +30,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
+import android.os.UserHandle;
import android.util.Log;
import java.io.IOException;
@@ -69,12 +71,16 @@ public class RegisteredComponentCache {
intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
- mContext.registerReceiver(receiver, intentFilter);
+ mContext.registerReceiverAsUser(receiver, UserHandle.ALL, intentFilter, null, null);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiver(receiver, sdFilter);
+ mContext.registerReceiverAsUser(receiver, UserHandle.ALL, sdFilter, null, null);
+ // Generate a new list upon switching users as well
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiverAsUser(receiver, UserHandle.ALL, userFilter, null, null);
}
public static class ComponentInfo {
@@ -137,13 +143,21 @@ public class RegisteredComponentCache {
}
void generateComponentsList() {
- PackageManager pm = mContext.getPackageManager();
+ PackageManager pm;
+ try {
+ UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
+ pm = mContext.createPackageContextAsUser("android", 0,
+ currentUser).getPackageManager();
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not create user package context");
+ return;
+ }
ArrayList<ComponentInfo> components = new ArrayList<ComponentInfo>();
- List<ResolveInfo> resolveInfos = pm.queryIntentActivities(new Intent(mAction),
- PackageManager.GET_META_DATA);
+ List<ResolveInfo> resolveInfos = pm.queryIntentActivitiesAsUser(new Intent(mAction),
+ PackageManager.GET_META_DATA, ActivityManager.getCurrentUser());
for (ResolveInfo resolveInfo : resolveInfos) {
try {
- parseComponentInfo(resolveInfo, components);
+ parseComponentInfo(pm, resolveInfo, components);
} catch (XmlPullParserException e) {
Log.w(TAG, "Unable to load component info " + resolveInfo.toString(), e);
} catch (IOException e) {
@@ -158,10 +172,9 @@ public class RegisteredComponentCache {
}
}
- void parseComponentInfo(ResolveInfo info, ArrayList<ComponentInfo> components)
- throws XmlPullParserException, IOException {
+ void parseComponentInfo(PackageManager pm, ResolveInfo info,
+ ArrayList<ComponentInfo> components) throws XmlPullParserException, IOException {
ActivityInfo ai = info.activityInfo;
- PackageManager pm = mContext.getPackageManager();
XmlResourceParser parser = null;
try {
diff --git a/src/com/android/nfc/handover/BluetoothHeadsetHandover.java b/src/com/android/nfc/handover/BluetoothHeadsetHandover.java
index 644ecbd..1377160 100644
--- a/src/com/android/nfc/handover/BluetoothHeadsetHandover.java
+++ b/src/com/android/nfc/handover/BluetoothHeadsetHandover.java
@@ -16,6 +16,7 @@
package com.android.nfc.handover;
+import android.app.ActivityManager;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -28,6 +29,7 @@ import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.UserHandle;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;
@@ -385,10 +387,10 @@ public class BluetoothHeadsetHandover implements BluetoothProfile.ServiceListene
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_MEDIA_PLAY));
- mContext.sendOrderedBroadcast(intent, null);
+ mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, null, null, 0, null, null);
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_MEDIA_PLAY));
- mContext.sendOrderedBroadcast(intent, null);
+ mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, null, null, 0, null, null);
}
void requestPairConfirmation() {
@@ -397,7 +399,7 @@ public class BluetoothHeadsetHandover implements BluetoothProfile.ServiceListene
dialogIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
- mContext.startActivity(dialogIntent);
+ mContext.startActivityAsUser(dialogIntent, new UserHandle(UserHandle.USER_CURRENT));
}
final Handler mHandler = new Handler() {
diff --git a/src/com/android/nfc/handover/HandoverManager.java b/src/com/android/nfc/handover/HandoverManager.java
index a514f85..e7e807d 100644
--- a/src/com/android/nfc/handover/HandoverManager.java
+++ b/src/com/android/nfc/handover/HandoverManager.java
@@ -33,11 +33,8 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Notification.Builder;
-import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -52,6 +49,7 @@ import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
@@ -387,7 +385,8 @@ public class HandoverManager implements BluetoothHeadsetHandover.Callback {
notBuilder.setContentText(mContext.getString(R.string.beam_touch_to_view));
Intent viewIntent = buildViewIntent();
- PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, viewIntent, 0);
+ PendingIntent contentIntent = PendingIntent.getActivityAsUser(
+ mContext, 0, viewIntent, 0, null, UserHandle.CURRENT);
notBuilder.setContentIntent(contentIntent);
@@ -407,7 +406,8 @@ public class HandoverManager implements BluetoothHeadsetHandover.Callback {
return;
}
- mNotificationManager.notify(mNotificationId, notBuilder.build());
+ mNotificationManager.notifyAsUser(null, mNotificationId, notBuilder.build(),
+ UserHandle.CURRENT);
}
synchronized void updateStateAndNotification(int newState) {