NfcActivityManager.java revision 56f299b87a891db38691cc0260f761c3ce8ef9ac
1aeb094b520d8ea49b74129927578f18f758c873eJason Sams/* 2aeb094b520d8ea49b74129927578f18f758c873eJason Sams * Copyright (C) 2011 The Android Open Source Project 3aeb094b520d8ea49b74129927578f18f758c873eJason Sams * 4aeb094b520d8ea49b74129927578f18f758c873eJason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 5aeb094b520d8ea49b74129927578f18f758c873eJason Sams * you may not use this file except in compliance with the License. 6aeb094b520d8ea49b74129927578f18f758c873eJason Sams * You may obtain a copy of the License at 7aeb094b520d8ea49b74129927578f18f758c873eJason Sams * 8aeb094b520d8ea49b74129927578f18f758c873eJason Sams * http://www.apache.org/licenses/LICENSE-2.0 9aeb094b520d8ea49b74129927578f18f758c873eJason Sams * 10aeb094b520d8ea49b74129927578f18f758c873eJason Sams * Unless required by applicable law or agreed to in writing, software 11aeb094b520d8ea49b74129927578f18f758c873eJason Sams * distributed under the License is distributed on an "AS IS" BASIS, 12aeb094b520d8ea49b74129927578f18f758c873eJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13aeb094b520d8ea49b74129927578f18f758c873eJason Sams * See the License for the specific language governing permissions and 14aeb094b520d8ea49b74129927578f18f758c873eJason Sams * limitations under the License. 15aeb094b520d8ea49b74129927578f18f758c873eJason Sams */ 16aeb094b520d8ea49b74129927578f18f758c873eJason Sams 17aeb094b520d8ea49b74129927578f18f758c873eJason Samspackage android.nfc; 18aeb094b520d8ea49b74129927578f18f758c873eJason Sams 19aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.app.Activity; 20aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.app.Application; 21aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.content.ContentProvider; 22aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.content.Intent; 23aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.net.Uri; 24aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.nfc.NfcAdapter.ReaderCallback; 25aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.os.Binder; 26aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.os.Bundle; 27aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.os.RemoteException; 28aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.os.UserHandle; 29aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport android.util.Log; 30aeb094b520d8ea49b74129927578f18f758c873eJason Sams 31aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport java.util.ArrayList; 32aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport java.util.LinkedList; 33aeb094b520d8ea49b74129927578f18f758c873eJason Samsimport java.util.List; 34aeb094b520d8ea49b74129927578f18f758c873eJason Sams 35aeb094b520d8ea49b74129927578f18f758c873eJason Sams/** 36aeb094b520d8ea49b74129927578f18f758c873eJason Sams * Manages NFC API's that are coupled to the life-cycle of an Activity. 37aeb094b520d8ea49b74129927578f18f758c873eJason Sams * 38aeb094b520d8ea49b74129927578f18f758c873eJason Sams * <p>Uses {@link Application#registerActivityLifecycleCallbacks} to hook 39aeb094b520d8ea49b74129927578f18f758c873eJason Sams * into activity life-cycle events such as onPause() and onResume(). 40aeb094b520d8ea49b74129927578f18f758c873eJason Sams * 41aeb094b520d8ea49b74129927578f18f758c873eJason Sams * @hide 42aeb094b520d8ea49b74129927578f18f758c873eJason Sams */ 43aeb094b520d8ea49b74129927578f18f758c873eJason Samspublic final class NfcActivityManager extends IAppCallback.Stub 44aeb094b520d8ea49b74129927578f18f758c873eJason Sams implements Application.ActivityLifecycleCallbacks { 45aeb094b520d8ea49b74129927578f18f758c873eJason Sams static final String TAG = NfcAdapter.TAG; 46aeb094b520d8ea49b74129927578f18f758c873eJason Sams static final Boolean DBG = false; 47605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams 48605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams final NfcAdapter mAdapter; 49aeb094b520d8ea49b74129927578f18f758c873eJason Sams final NfcEvent mDefaultEvent; // cached NfcEvent (its currently always the same) 50aeb094b520d8ea49b74129927578f18f758c873eJason Sams 51aeb094b520d8ea49b74129927578f18f758c873eJason Sams // All objects in the lists are protected by this 52aeb094b520d8ea49b74129927578f18f758c873eJason Sams final List<NfcApplicationState> mApps; // Application(s) that have NFC state. Usually one 53aeb094b520d8ea49b74129927578f18f758c873eJason Sams final List<NfcActivityState> mActivities; // Activities that have NFC state 54aeb094b520d8ea49b74129927578f18f758c873eJason Sams 55aeb094b520d8ea49b74129927578f18f758c873eJason Sams /** 56aeb094b520d8ea49b74129927578f18f758c873eJason Sams * NFC State associated with an {@link Application}. 57aeb094b520d8ea49b74129927578f18f758c873eJason Sams */ 58aeb094b520d8ea49b74129927578f18f758c873eJason Sams class NfcApplicationState { 59605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams int refCount = 0; 60605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams final Application app; 61aeb094b520d8ea49b74129927578f18f758c873eJason Sams public NfcApplicationState(Application app) { 62aeb094b520d8ea49b74129927578f18f758c873eJason Sams this.app = app; 63aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 64aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void register() { 65aeb094b520d8ea49b74129927578f18f758c873eJason Sams refCount++; 66aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (refCount == 1) { 67aeb094b520d8ea49b74129927578f18f758c873eJason Sams this.app.registerActivityLifecycleCallbacks(NfcActivityManager.this); 68aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 69aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 70aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void unregister() { 71605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams refCount--; 72aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (refCount == 0) { 73aeb094b520d8ea49b74129927578f18f758c873eJason Sams this.app.unregisterActivityLifecycleCallbacks(NfcActivityManager.this); 74aeb094b520d8ea49b74129927578f18f758c873eJason Sams } else if (refCount < 0) { 75aeb094b520d8ea49b74129927578f18f758c873eJason Sams Log.e(TAG, "-ve refcount for " + app); 76aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 77aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 78605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams } 79aeb094b520d8ea49b74129927578f18f758c873eJason Sams 80aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcApplicationState findAppState(Application app) { 81aeb094b520d8ea49b74129927578f18f758c873eJason Sams for (NfcApplicationState appState : mApps) { 82aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (appState.app == app) { 83aeb094b520d8ea49b74129927578f18f758c873eJason Sams return appState; 84aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 85605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams } 86aeb094b520d8ea49b74129927578f18f758c873eJason Sams return null; 87aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 88aeb094b520d8ea49b74129927578f18f758c873eJason Sams 89aeb094b520d8ea49b74129927578f18f758c873eJason Sams void registerApplication(Application app) { 90aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcApplicationState appState = findAppState(app); 91aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (appState == null) { 92605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams appState = new NfcApplicationState(app); 93aeb094b520d8ea49b74129927578f18f758c873eJason Sams mApps.add(appState); 94aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 95aeb094b520d8ea49b74129927578f18f758c873eJason Sams appState.register(); 96aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 97aeb094b520d8ea49b74129927578f18f758c873eJason Sams 98aeb094b520d8ea49b74129927578f18f758c873eJason Sams void unregisterApplication(Application app) { 99aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcApplicationState appState = findAppState(app); 100aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (appState == null) { 101a490f1003a76286e0f00606adff4ef85fdd78b02Jim Miller Log.e(TAG, "app was not registered " + app); 102a490f1003a76286e0f00606adff4ef85fdd78b02Jim Miller return; 103a490f1003a76286e0f00606adff4ef85fdd78b02Jim Miller } 104383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk appState.unregister(); 105a490f1003a76286e0f00606adff4ef85fdd78b02Jim Miller } 106a490f1003a76286e0f00606adff4ef85fdd78b02Jim Miller 107aeb094b520d8ea49b74129927578f18f758c873eJason Sams /** 108aeb094b520d8ea49b74129927578f18f758c873eJason Sams * NFC state associated with an {@link Activity} 109aeb094b520d8ea49b74129927578f18f758c873eJason Sams */ 110383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk class NfcActivityState { 111aeb094b520d8ea49b74129927578f18f758c873eJason Sams boolean resumed = false; 112aeb094b520d8ea49b74129927578f18f758c873eJason Sams Activity activity; 113aeb094b520d8ea49b74129927578f18f758c873eJason Sams NdefMessage ndefMessage = null; // static NDEF message 114aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcAdapter.CreateNdefMessageCallback ndefMessageCallback = null; 115aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback = null; 116383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk NfcAdapter.CreateBeamUrisCallback uriCallback = null; 117aeb094b520d8ea49b74129927578f18f758c873eJason Sams Uri[] uris = null; 118aeb094b520d8ea49b74129927578f18f758c873eJason Sams int flags = 0; 119aeb094b520d8ea49b74129927578f18f758c873eJason Sams int readerModeFlags = 0; 1206445e5210c6d7f8689e94be9026153d017c9545bJason Sams NfcAdapter.ReaderCallback readerCallback = null; 1216445e5210c6d7f8689e94be9026153d017c9545bJason Sams Bundle readerModeExtras = null; 122383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk Binder token; 123605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams 1246445e5210c6d7f8689e94be9026153d017c9545bJason Sams public NfcActivityState(Activity activity) { 125383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk if (activity.getWindow().isDestroyed()) { 1266445e5210c6d7f8689e94be9026153d017c9545bJason Sams throw new IllegalStateException("activity is already destroyed"); 1276445e5210c6d7f8689e94be9026153d017c9545bJason Sams } 12895333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk // Check if activity is resumed right now, as we will not 12995333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk // immediately get a callback for that. 13095333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk resumed = activity.isResumed(); 131383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk 13295333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk this.activity = activity; 13395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk this.token = new Binder(); 134aeb094b520d8ea49b74129927578f18f758c873eJason Sams registerApplication(activity.getApplication()); 135aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 136aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void destroy() { 137aeb094b520d8ea49b74129927578f18f758c873eJason Sams unregisterApplication(activity.getApplication()); 138aeb094b520d8ea49b74129927578f18f758c873eJason Sams resumed = false; 139aeb094b520d8ea49b74129927578f18f758c873eJason Sams activity = null; 140aeb094b520d8ea49b74129927578f18f758c873eJason Sams ndefMessage = null; 141aeb094b520d8ea49b74129927578f18f758c873eJason Sams ndefMessageCallback = null; 142aeb094b520d8ea49b74129927578f18f758c873eJason Sams onNdefPushCompleteCallback = null; 143aeb094b520d8ea49b74129927578f18f758c873eJason Sams uriCallback = null; 144aeb094b520d8ea49b74129927578f18f758c873eJason Sams uris = null; 145aeb094b520d8ea49b74129927578f18f758c873eJason Sams readerModeFlags = 0; 146aeb094b520d8ea49b74129927578f18f758c873eJason Sams token = null; 147aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 148aeb094b520d8ea49b74129927578f18f758c873eJason Sams @Override 149aeb094b520d8ea49b74129927578f18f758c873eJason Sams public String toString() { 150aeb094b520d8ea49b74129927578f18f758c873eJason Sams StringBuilder s = new StringBuilder("[").append(" "); 151aeb094b520d8ea49b74129927578f18f758c873eJason Sams s.append(ndefMessage).append(" ").append(ndefMessageCallback).append(" "); 152aeb094b520d8ea49b74129927578f18f758c873eJason Sams s.append(uriCallback).append(" "); 153aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (uris != null) { 154aeb094b520d8ea49b74129927578f18f758c873eJason Sams for (Uri uri : uris) { 155aeb094b520d8ea49b74129927578f18f758c873eJason Sams s.append(onNdefPushCompleteCallback).append(" ").append(uri).append("]"); 156aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 157aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 158aeb094b520d8ea49b74129927578f18f758c873eJason Sams return s.toString(); 159aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 160aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 161aeb094b520d8ea49b74129927578f18f758c873eJason Sams 162aeb094b520d8ea49b74129927578f18f758c873eJason Sams /** find activity state from mActivities */ 163886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk synchronized NfcActivityState findActivityState(Activity activity) { 164886f11ade9dde05485cb11c0d67d87f76a428f6cAlex Sakhartchouk for (NfcActivityState state : mActivities) { 16579f52df541f87ac07709e770cd79f14dd1a05e93Jason Sams if (state.activity == activity) { 166aeb094b520d8ea49b74129927578f18f758c873eJason Sams return state; 167aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 168aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 169aeb094b520d8ea49b74129927578f18f758c873eJason Sams return null; 170aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 171aeb094b520d8ea49b74129927578f18f758c873eJason Sams 172aeb094b520d8ea49b74129927578f18f758c873eJason Sams /** find or create activity state from mActivities */ 173aeb094b520d8ea49b74129927578f18f758c873eJason Sams synchronized NfcActivityState getActivityState(Activity activity) { 174aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcActivityState state = findActivityState(activity); 175aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (state == null) { 176aeb094b520d8ea49b74129927578f18f758c873eJason Sams state = new NfcActivityState(activity); 177aeb094b520d8ea49b74129927578f18f758c873eJason Sams mActivities.add(state); 178aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 179aeb094b520d8ea49b74129927578f18f758c873eJason Sams return state; 180aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 181aeb094b520d8ea49b74129927578f18f758c873eJason Sams 182aeb094b520d8ea49b74129927578f18f758c873eJason Sams synchronized NfcActivityState findResumedActivityState() { 183aeb094b520d8ea49b74129927578f18f758c873eJason Sams for (NfcActivityState state : mActivities) { 184aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (state.resumed) { 185aeb094b520d8ea49b74129927578f18f758c873eJason Sams return state; 186aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 187aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 188aeb094b520d8ea49b74129927578f18f758c873eJason Sams return null; 189aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 190aeb094b520d8ea49b74129927578f18f758c873eJason Sams 191aeb094b520d8ea49b74129927578f18f758c873eJason Sams synchronized void destroyActivityState(Activity activity) { 192aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcActivityState activityState = findActivityState(activity); 193aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (activityState != null) { 194aeb094b520d8ea49b74129927578f18f758c873eJason Sams activityState.destroy(); 195aeb094b520d8ea49b74129927578f18f758c873eJason Sams mActivities.remove(activityState); 196aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 197aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 198bdb046001675f949e7e9b2cd0bfd63a5889d97edJason Sams 199aeb094b520d8ea49b74129927578f18f758c873eJason Sams public NfcActivityManager(NfcAdapter adapter) { 200aeb094b520d8ea49b74129927578f18f758c873eJason Sams mAdapter = adapter; 201aeb094b520d8ea49b74129927578f18f758c873eJason Sams mActivities = new LinkedList<NfcActivityState>(); 202aeb094b520d8ea49b74129927578f18f758c873eJason Sams mApps = new ArrayList<NfcApplicationState>(1); // Android VM usually has 1 app 203aeb094b520d8ea49b74129927578f18f758c873eJason Sams mDefaultEvent = new NfcEvent(mAdapter); 204aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 205aeb094b520d8ea49b74129927578f18f758c873eJason Sams 206aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, 207aeb094b520d8ea49b74129927578f18f758c873eJason Sams Bundle extras) { 208aeb094b520d8ea49b74129927578f18f758c873eJason Sams boolean isResumed; 209aeb094b520d8ea49b74129927578f18f758c873eJason Sams Binder token; 210aeb094b520d8ea49b74129927578f18f758c873eJason Sams synchronized (NfcActivityManager.this) { 211aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcActivityState state = getActivityState(activity); 212aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.readerCallback = callback; 213aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.readerModeFlags = flags; 214aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.readerModeExtras = extras; 215aeb094b520d8ea49b74129927578f18f758c873eJason Sams token = state.token; 216aeb094b520d8ea49b74129927578f18f758c873eJason Sams isResumed = state.resumed; 217aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 218aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (isResumed) { 219aeb094b520d8ea49b74129927578f18f758c873eJason Sams setReaderMode(token, flags, extras); 220aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 221aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 222aeb094b520d8ea49b74129927578f18f758c873eJason Sams 223aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void disableReaderMode(Activity activity) { 224aeb094b520d8ea49b74129927578f18f758c873eJason Sams boolean isResumed; 225aeb094b520d8ea49b74129927578f18f758c873eJason Sams Binder token; 226bdb046001675f949e7e9b2cd0bfd63a5889d97edJason Sams synchronized (NfcActivityManager.this) { 227aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcActivityState state = getActivityState(activity); 228aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.readerCallback = null; 229aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.readerModeFlags = 0; 230aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.readerModeExtras = null; 231aeb094b520d8ea49b74129927578f18f758c873eJason Sams token = state.token; 232aeb094b520d8ea49b74129927578f18f758c873eJason Sams isResumed = state.resumed; 233aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 234aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (isResumed) { 235aeb094b520d8ea49b74129927578f18f758c873eJason Sams setReaderMode(token, 0, null); 236aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 237aeb094b520d8ea49b74129927578f18f758c873eJason Sams 2384e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk } 2394e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk 240605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams public void setReaderMode(Binder token, int flags, Bundle extras) { 2414e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk if (DBG) Log.d(TAG, "Setting reader mode"); 2424e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk try { 243aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcAdapter.sService.setReaderMode(token, this, flags, extras); 244aeb094b520d8ea49b74129927578f18f758c873eJason Sams } catch (RemoteException e) { 245aeb094b520d8ea49b74129927578f18f758c873eJason Sams mAdapter.attemptDeadServiceRecovery(e); 246aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 247aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 248aeb094b520d8ea49b74129927578f18f758c873eJason Sams 2494e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk public void setNdefPushContentUri(Activity activity, Uri[] uris) { 250aeb094b520d8ea49b74129927578f18f758c873eJason Sams boolean isResumed; 251605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams synchronized (NfcActivityManager.this) { 252aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcActivityState state = getActivityState(activity); 2534e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk state.uris = uris; 254aeb094b520d8ea49b74129927578f18f758c873eJason Sams isResumed = state.resumed; 255aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 256aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (isResumed) { 2574e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk requestNfcServiceCallback(); 2584e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk } 2594e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk } 2604e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk 2614e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk 262605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams public void setNdefPushContentUriCallback(Activity activity, 2634e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk NfcAdapter.CreateBeamUrisCallback callback) { 2644e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk boolean isResumed; 2654e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk synchronized (NfcActivityManager.this) { 2664e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk NfcActivityState state = getActivityState(activity); 2674e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk state.uriCallback = callback; 2684e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk isResumed = state.resumed; 269aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 270aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (isResumed) { 271ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk requestNfcServiceCallback(); 272ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk } 273ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk } 274605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams 275ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk public void setNdefPushMessage(Activity activity, NdefMessage message, int flags) { 276ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk boolean isResumed; 277ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk synchronized (NfcActivityManager.this) { 278ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk NfcActivityState state = getActivityState(activity); 279ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk state.ndefMessage = message; 280ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk state.flags = flags; 281ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk isResumed = state.resumed; 282ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk } 283ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk if (isResumed) { 284ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk requestNfcServiceCallback(); 285ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk } 286aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 287aeb094b520d8ea49b74129927578f18f758c873eJason Sams 288aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void setNdefPushMessageCallback(Activity activity, 289aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcAdapter.CreateNdefMessageCallback callback, int flags) { 290aeb094b520d8ea49b74129927578f18f758c873eJason Sams boolean isResumed; 291aeb094b520d8ea49b74129927578f18f758c873eJason Sams synchronized (NfcActivityManager.this) { 292aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcActivityState state = getActivityState(activity); 293aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.ndefMessageCallback = callback; 294aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.flags = flags; 2956445e5210c6d7f8689e94be9026153d017c9545bJason Sams isResumed = state.resumed; 296383e5b1f68c321a77bfd7466fa1171a9bfab4a6fAlex Sakhartchouk } 297aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (isResumed) { 298aeb094b520d8ea49b74129927578f18f758c873eJason Sams requestNfcServiceCallback(); 29922fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams } 300aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 301605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams 302aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void setOnNdefPushCompleteCallback(Activity activity, 303aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcAdapter.OnNdefPushCompleteCallback callback) { 304aeb094b520d8ea49b74129927578f18f758c873eJason Sams boolean isResumed; 30522fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams synchronized (NfcActivityManager.this) { 30622fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams NfcActivityState state = getActivityState(activity); 307605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams state.onNdefPushCompleteCallback = callback; 30822fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams isResumed = state.resumed; 30922fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams } 31022fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams if (isResumed) { 311aeb094b520d8ea49b74129927578f18f758c873eJason Sams requestNfcServiceCallback(); 312aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 313aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 314605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams 315aeb094b520d8ea49b74129927578f18f758c873eJason Sams /** 316aeb094b520d8ea49b74129927578f18f758c873eJason Sams * Request or unrequest NFC service callbacks. 317aeb094b520d8ea49b74129927578f18f758c873eJason Sams * Makes IPC call - do not hold lock. 318aeb094b520d8ea49b74129927578f18f758c873eJason Sams */ 31922fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams void requestNfcServiceCallback() { 320aeb094b520d8ea49b74129927578f18f758c873eJason Sams try { 321aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcAdapter.sService.setAppCallback(this); 32222fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams } catch (RemoteException e) { 32322fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams mAdapter.attemptDeadServiceRecovery(e); 32422fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams } 325aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 32622fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams 32722fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams /** Callback from NFC service, usually on binder thread */ 328aeb094b520d8ea49b74129927578f18f758c873eJason Sams @Override 329aeb094b520d8ea49b74129927578f18f758c873eJason Sams public BeamShareData createBeamShareData() { 33022fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams NfcAdapter.CreateNdefMessageCallback ndefCallback; 331aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcAdapter.CreateBeamUrisCallback urisCallback; 332aeb094b520d8ea49b74129927578f18f758c873eJason Sams NdefMessage message; 33322fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams Activity activity; 33422fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams Uri[] uris; 33522fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams int flags; 33622fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams synchronized (NfcActivityManager.this) { 33722fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams NfcActivityState state = findResumedActivityState(); 33822fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams if (state == null) return null; 339aeb094b520d8ea49b74129927578f18f758c873eJason Sams 340aeb094b520d8ea49b74129927578f18f758c873eJason Sams ndefCallback = state.ndefMessageCallback; 341aeb094b520d8ea49b74129927578f18f758c873eJason Sams urisCallback = state.uriCallback; 342aeb094b520d8ea49b74129927578f18f758c873eJason Sams message = state.ndefMessage; 343aeb094b520d8ea49b74129927578f18f758c873eJason Sams uris = state.uris; 344aeb094b520d8ea49b74129927578f18f758c873eJason Sams flags = state.flags; 345aeb094b520d8ea49b74129927578f18f758c873eJason Sams activity = state.activity; 346aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 347aeb094b520d8ea49b74129927578f18f758c873eJason Sams 348aeb094b520d8ea49b74129927578f18f758c873eJason Sams // Make callbacks without lock 349aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (ndefCallback != null) { 350aeb094b520d8ea49b74129927578f18f758c873eJason Sams message = ndefCallback.createNdefMessage(mDefaultEvent); 351aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 352aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (urisCallback != null) { 353d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uris = urisCallback.createBeamUris(mDefaultEvent); 354d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (uris != null) { 355605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams ArrayList<Uri> validUris = new ArrayList<Uri>(); 356d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk for (Uri uri : uris) { 357d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (uri == null) { 358d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Log.e(TAG, "Uri not allowed to be null."); 359d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk continue; 360d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 361d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk String scheme = uri.getScheme(); 362d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk if (scheme == null || (!scheme.equalsIgnoreCase("file") && 363d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk !scheme.equalsIgnoreCase("content"))) { 364d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk Log.e(TAG, "Uri needs to have " + 365d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk "either scheme file or scheme content"); 366d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk continue; 367d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 368d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uri = ContentProvider.maybeAddUserId(uri, UserHandle.myUserId()); 369605048a9f9af925782f6c90bc1cdc5af59e337d8Jason Sams validUris.add(uri); 370d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk } 371d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk 372d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk uris = validUris.toArray(new Uri[validUris.size()]); 373aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 3749fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk } 3759fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk if (uris != null && uris.length > 0) { 3769fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk for (Uri uri : uris) { 3779fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk // Grant the NFC process permission to read these URIs 3789fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk activity.grantUriPermission("com.android.nfc", uri, 3799fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk Intent.FLAG_GRANT_READ_URI_PERMISSION); 380aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 381aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 382aeb094b520d8ea49b74129927578f18f758c873eJason Sams return new BeamShareData(message, uris, UserHandle.CURRENT, flags); 383aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 384aeb094b520d8ea49b74129927578f18f758c873eJason Sams 385aeb094b520d8ea49b74129927578f18f758c873eJason Sams /** Callback from NFC service, usually on binder thread */ 386aeb094b520d8ea49b74129927578f18f758c873eJason Sams @Override 387aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void onNdefPushComplete() { 388aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcAdapter.OnNdefPushCompleteCallback callback; 389aeb094b520d8ea49b74129927578f18f758c873eJason Sams synchronized (NfcActivityManager.this) { 390aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcActivityState state = findResumedActivityState(); 391aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (state == null) return; 392aeb094b520d8ea49b74129927578f18f758c873eJason Sams 393aeb094b520d8ea49b74129927578f18f758c873eJason Sams callback = state.onNdefPushCompleteCallback; 394aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 395aeb094b520d8ea49b74129927578f18f758c873eJason Sams 396aeb094b520d8ea49b74129927578f18f758c873eJason Sams // Make callback without lock 397aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (callback != null) { 398aeb094b520d8ea49b74129927578f18f758c873eJason Sams callback.onNdefPushComplete(mDefaultEvent); 399aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 400aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 401aeb094b520d8ea49b74129927578f18f758c873eJason Sams 4027349547db61d2d458b31c074b902d56d082e5d84Jason Sams @Override 4037349547db61d2d458b31c074b902d56d082e5d84Jason Sams public void onTagDiscovered(Tag tag) throws RemoteException { 4047349547db61d2d458b31c074b902d56d082e5d84Jason Sams NfcAdapter.ReaderCallback callback; 4057349547db61d2d458b31c074b902d56d082e5d84Jason Sams synchronized (NfcActivityManager.this) { 4067349547db61d2d458b31c074b902d56d082e5d84Jason Sams NfcActivityState state = findResumedActivityState(); 4077349547db61d2d458b31c074b902d56d082e5d84Jason Sams if (state == null) return; 40822fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams 4097349547db61d2d458b31c074b902d56d082e5d84Jason Sams callback = state.readerCallback; 4107349547db61d2d458b31c074b902d56d082e5d84Jason Sams } 4117349547db61d2d458b31c074b902d56d082e5d84Jason Sams 41222fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams // Make callback without lock 41395333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk if (callback != null) { 41495333f998fd4a983f89e5128e85f6f710d200bd9Alex Sakhartchouk callback.onTagDiscovered(tag); 4156445e5210c6d7f8689e94be9026153d017c9545bJason Sams } 4166445e5210c6d7f8689e94be9026153d017c9545bJason Sams 4177349547db61d2d458b31c074b902d56d082e5d84Jason Sams } 4187349547db61d2d458b31c074b902d56d082e5d84Jason Sams /** Callback from Activity life-cycle, on main thread */ 41922fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams @Override 4207349547db61d2d458b31c074b902d56d082e5d84Jason Sams public void onActivityCreated(Activity activity, Bundle savedInstanceState) { /* NO-OP */ } 4218c88090e8cccab103eebe2ff569e116e9f5fb208Jason Sams 4227349547db61d2d458b31c074b902d56d082e5d84Jason Sams /** Callback from Activity life-cycle, on main thread */ 42322fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams @Override 4247349547db61d2d458b31c074b902d56d082e5d84Jason Sams public void onActivityStarted(Activity activity) { /* NO-OP */ } 4257349547db61d2d458b31c074b902d56d082e5d84Jason Sams 4267349547db61d2d458b31c074b902d56d082e5d84Jason Sams /** Callback from Activity life-cycle, on main thread */ 4277349547db61d2d458b31c074b902d56d082e5d84Jason Sams @Override 42822fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams public void onActivityResumed(Activity activity) { 4294e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk int readerModeFlags = 0; 4307349547db61d2d458b31c074b902d56d082e5d84Jason Sams Bundle readerModeExtras = null; 4317349547db61d2d458b31c074b902d56d082e5d84Jason Sams Binder token; 432ba4aa5c768a498bc3fbb8cb5547b7a9ad6f4b771Alex Sakhartchouk synchronized (NfcActivityManager.this) { 4334e9a7a8ded109e16b163789274899447cef02642Alex Sakhartchouk NfcActivityState state = findActivityState(activity); 4347349547db61d2d458b31c074b902d56d082e5d84Jason Sams if (DBG) Log.d(TAG, "onResume() for " + activity + " " + state); 4357349547db61d2d458b31c074b902d56d082e5d84Jason Sams if (state == null) return; 43622fa371bf64b8aae786acfe5d711af21afb13a93Jason Sams state.resumed = true; 437d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk token = state.token; 438d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk readerModeFlags = state.readerModeFlags; 439d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk readerModeExtras = state.readerModeExtras; 4407349547db61d2d458b31c074b902d56d082e5d84Jason Sams } 4419fc9f0375a92fe22fecb3782b18a5c6060a07290Alex Sakhartchouk if (readerModeFlags != 0) { 442d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk setReaderMode(token, readerModeFlags, readerModeExtras); 443aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 4447349547db61d2d458b31c074b902d56d082e5d84Jason Sams requestNfcServiceCallback(); 445aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 446aeb094b520d8ea49b74129927578f18f758c873eJason Sams 447aeb094b520d8ea49b74129927578f18f758c873eJason Sams /** Callback from Activity life-cycle, on main thread */ 448aeb094b520d8ea49b74129927578f18f758c873eJason Sams @Override 449aeb094b520d8ea49b74129927578f18f758c873eJason Sams public void onActivityPaused(Activity activity) { 450aeb094b520d8ea49b74129927578f18f758c873eJason Sams boolean readerModeFlagsSet; 451aeb094b520d8ea49b74129927578f18f758c873eJason Sams Binder token; 452aeb094b520d8ea49b74129927578f18f758c873eJason Sams synchronized (NfcActivityManager.this) { 453aeb094b520d8ea49b74129927578f18f758c873eJason Sams NfcActivityState state = findActivityState(activity); 454aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (DBG) Log.d(TAG, "onPause() for " + activity + " " + state); 455aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (state == null) return; 456aeb094b520d8ea49b74129927578f18f758c873eJason Sams state.resumed = false; 457aeb094b520d8ea49b74129927578f18f758c873eJason Sams token = state.token; 458aeb094b520d8ea49b74129927578f18f758c873eJason Sams readerModeFlagsSet = state.readerModeFlags != 0; 459aeb094b520d8ea49b74129927578f18f758c873eJason Sams } 460aeb094b520d8ea49b74129927578f18f758c873eJason Sams if (readerModeFlagsSet) { 461aeb094b520d8ea49b74129927578f18f758c873eJason Sams // Restore default p2p modes 462 setReaderMode(token, 0, null); 463 } 464 } 465 466 /** Callback from Activity life-cycle, on main thread */ 467 @Override 468 public void onActivityStopped(Activity activity) { /* NO-OP */ } 469 470 /** Callback from Activity life-cycle, on main thread */ 471 @Override 472 public void onActivitySaveInstanceState(Activity activity, Bundle outState) { /* NO-OP */ } 473 474 /** Callback from Activity life-cycle, on main thread */ 475 @Override 476 public void onActivityDestroyed(Activity activity) { 477 synchronized (NfcActivityManager.this) { 478 NfcActivityState state = findActivityState(activity); 479 if (DBG) Log.d(TAG, "onDestroy() for " + activity + " " + state); 480 if (state != null) { 481 // release all associated references 482 destroyActivityState(activity); 483 } 484 } 485 } 486 487} 488