NfcActivityManager.java revision 1d7e9062330a5a02247752de32a68ecbeba82783
1c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly/*
2c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * Copyright (C) 2011 The Android Open Source Project
3c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly *
4c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * you may not use this file except in compliance with the License.
6c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * You may obtain a copy of the License at
7c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly *
8c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly *
10c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * Unless required by applicable law or agreed to in writing, software
11c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * See the License for the specific language governing permissions and
14c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * limitations under the License.
15c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly */
16c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
17c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pellypackage android.nfc;
18c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
19c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pellyimport android.app.Activity;
208ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pellyimport android.app.Application;
211d7e9062330a5a02247752de32a68ecbeba82783Nick Pellyimport android.net.Uri;
228ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pellyimport android.os.Bundle;
23c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pellyimport android.os.RemoteException;
24c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pellyimport android.util.Log;
25c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
268ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pellyimport java.util.ArrayList;
278ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pellyimport java.util.LinkedList;
288ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pellyimport java.util.List;
29c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
30c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly/**
31c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * Manages NFC API's that are coupled to the life-cycle of an Activity.
32c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly *
338ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly * <p>Uses {@link Application#registerActivityLifecycleCallbacks} to hook
348ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly * into activity life-cycle events such as onPause() and onResume().
35c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly *
36c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly * @hide
37c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly */
388ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pellypublic final class NfcActivityManager extends INdefPushCallback.Stub
398ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        implements Application.ActivityLifecycleCallbacks {
40c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    static final String TAG = NfcAdapter.TAG;
41c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    static final Boolean DBG = false;
42c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
43c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    final NfcAdapter mAdapter;
448ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    final NfcEvent mDefaultEvent;  // cached NfcEvent (its currently always the same)
458ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
468ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    // All objects in the lists are protected by this
478ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    final List<NfcApplicationState> mApps;  // Application(s) that have NFC state. Usually one
488ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    final List<NfcActivityState> mActivities;  // Activities that have NFC state
49c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
50c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    /**
518ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly     * NFC State associated with an {@link Application}.
52c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly     */
538ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    class NfcApplicationState {
548ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        int refCount = 0;
558ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        final Application app;
568ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        public NfcApplicationState(Application app) {
578ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            this.app = app;
588ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        }
598ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        public void register() {
608ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            refCount++;
618ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (refCount == 1) {
628ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                this.app.registerActivityLifecycleCallbacks(NfcActivityManager.this);
638ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            }
648ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        }
658ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        public void unregister() {
668ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            refCount--;
678ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (refCount == 0) {
688ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                this.app.unregisterActivityLifecycleCallbacks(NfcActivityManager.this);
698ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            } else if (refCount < 0) {
708ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                Log.e(TAG, "-ve refcount for " + app);
718ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            }
72c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
73c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
74c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
758ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    NfcApplicationState findAppState(Application app) {
768ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        for (NfcApplicationState appState : mApps) {
778ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (appState.app == app) {
788ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                return appState;
798ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            }
808ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        }
818ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        return null;
82c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
83c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
848ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    void registerApplication(Application app) {
858ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NfcApplicationState appState = findAppState(app);
868ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        if (appState == null) {
878ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            appState = new NfcApplicationState(app);
888ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            mApps.add(appState);
89c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
908ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        appState.register();
91c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
92c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
938ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    void unregisterApplication(Application app) {
948ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NfcApplicationState appState = findAppState(app);
958ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        if (appState == null) {
968ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            Log.e(TAG, "app was not registered " + app);
978ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            return;
98c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
998ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        appState.unregister();
100c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
101c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
1023433a8ae5abf7c518277e2e00c141e1dec83600cMartijn Coenen    /**
1038ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly     * NFC state associated with an {@link Activity}
1043433a8ae5abf7c518277e2e00c141e1dec83600cMartijn Coenen     */
1058ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    class NfcActivityState {
1068ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        boolean resumed = false;
1078ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        Activity activity;
1088ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NdefMessage ndefMessage = null;  // static NDEF message
1098ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NfcAdapter.CreateNdefMessageCallback ndefMessageCallback = null;
1108ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback = null;
1111d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        Uri uri = null;
1121d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        String mimeType = null;
1138ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        public NfcActivityState(Activity activity) {
1148ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (activity.getWindow().isDestroyed()) {
1158ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                throw new IllegalStateException("activity is already destroyed");
1168ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            }
1178ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            this.activity = activity;
1188ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            registerApplication(activity.getApplication());
119c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
1208ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        public void destroy() {
1218ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            unregisterApplication(activity.getApplication());
1228ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            resumed = false;
1238ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            activity = null;
1248ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            ndefMessage = null;
1258ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            ndefMessageCallback = null;
1268ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            onNdefPushCompleteCallback = null;
1271d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            uri = null;
1281d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            mimeType = null;
129c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
1308ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        @Override
1318ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        public String toString() {
1328ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            StringBuilder s = new StringBuilder("[").append(" ");
1338ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            s.append(ndefMessage).append(" ").append(ndefMessageCallback).append(" ");
1341d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            s.append(onNdefPushCompleteCallback).append(" ").append(uri).append("]");
1358ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            return s.toString();
136c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
137c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
138c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
1398ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** find activity state from mActivities */
1408ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    synchronized NfcActivityState findActivityState(Activity activity) {
1418ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        for (NfcActivityState state : mActivities) {
1428ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (state.activity == activity) {
1438ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                return state;
1448ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            }
145c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
1468ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        return null;
1478ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    }
1488ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
1498ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** find or create activity state from mActivities */
1508ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    synchronized NfcActivityState getActivityState(Activity activity) {
1518ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NfcActivityState state = findActivityState(activity);
1528ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        if (state == null) {
1538ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            state = new NfcActivityState(activity);
1548ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            mActivities.add(state);
155c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
1568ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        return state;
1578ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    }
1588ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
1598ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    synchronized NfcActivityState findResumedActivityState() {
1608ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        for (NfcActivityState state : mActivities) {
1618ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (state.resumed) {
1628ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                return state;
1638ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            }
164c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
1658ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        return null;
166c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
167c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
1688ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    synchronized void destroyActivityState(Activity activity) {
1698ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NfcActivityState activityState = findActivityState(activity);
1708ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        if (activityState != null) {
1718ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            activityState.destroy();
1728ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            mActivities.remove(activityState);
173c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
1748ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    }
1758ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
1768ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public NfcActivityManager(NfcAdapter adapter) {
1778ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        mAdapter = adapter;
1788ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        mActivities = new LinkedList<NfcActivityState>();
1798ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        mApps = new ArrayList<NfcApplicationState>(1);  // Android VM usually has 1 app
1808ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        mDefaultEvent = new NfcEvent(mAdapter);
1818ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    }
1828ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
1831d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    public void setNdefPushContentUri(Activity activity, String mimeType, Uri uri) {
1841d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        boolean isResumed;
1851d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        synchronized (NfcActivityManager.this) {
1861d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            NfcActivityState state = getActivityState(activity);
1871d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            state.uri = uri;
1881d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            state.mimeType = mimeType;
1891d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            isResumed = state.resumed;
1901d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        }
1911d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        if (isResumed) {
1921d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            requestNfcServiceCallback(true);
1931d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        }
1941d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    }
1951d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly
1968ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void setNdefPushMessage(Activity activity, NdefMessage message) {
1978ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        boolean isResumed;
1988ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        synchronized (NfcActivityManager.this) {
1998ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcActivityState state = getActivityState(activity);
2008ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            state.ndefMessage = message;
2018ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            isResumed = state.resumed;
202c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
2038ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        if (isResumed) {
2048ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            requestNfcServiceCallback(true);
205c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
206c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
207c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
2088ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void setNdefPushMessageCallback(Activity activity,
2098ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcAdapter.CreateNdefMessageCallback callback) {
2108ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        boolean isResumed;
2118ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        synchronized (NfcActivityManager.this) {
2128ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcActivityState state = getActivityState(activity);
2138ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            state.ndefMessageCallback = callback;
2148ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            isResumed = state.resumed;
2158ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        }
2168ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        if (isResumed) {
2178ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            requestNfcServiceCallback(true);
218c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
219c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
220c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
2218ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void setOnNdefPushCompleteCallback(Activity activity,
2228ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcAdapter.OnNdefPushCompleteCallback callback) {
2238ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        boolean isResumed;
2248ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        synchronized (NfcActivityManager.this) {
2258ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcActivityState state = getActivityState(activity);
2268ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            state.onNdefPushCompleteCallback = callback;
2278ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            isResumed = state.resumed;
2288ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        }
2298ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        if (isResumed) {
2308ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            requestNfcServiceCallback(true);
231c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
232c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
233c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
234c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    /**
2358ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly     * Request or unrequest NFC service callbacks for NDEF push.
2368ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly     * Makes IPC call - do not hold lock.
2378ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly     * TODO: Do not do IPC on every onPause/onResume
238c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly     */
2398ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    void requestNfcServiceCallback(boolean request) {
240c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        try {
2418ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcAdapter.sService.setNdefPushCallback(request ? this : null);
242c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        } catch (RemoteException e) {
243c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly            mAdapter.attemptDeadServiceRecovery(e);
244c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
245c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
246c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
2478ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from NFC service, usually on binder thread */
248c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    @Override
249c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    public NdefMessage createMessage() {
2508ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NfcAdapter.CreateNdefMessageCallback callback;
2518ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NdefMessage message;
252c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        synchronized (NfcActivityManager.this) {
2538ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcActivityState state = findResumedActivityState();
2548ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (state == null) return null;
2558ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
2568ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            callback = state.ndefMessageCallback;
2578ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            message = state.ndefMessage;
258c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
259c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
2608ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        // Make callback without lock
261c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        if (callback != null) {
262c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly            return callback.createNdefMessage(mDefaultEvent);
2638ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        } else {
2648ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            return message;
265c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
266c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
267c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
2688ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from NFC service, usually on binder thread */
269c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    @Override
2701d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    public Uri getUri() {
2711d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        synchronized (NfcActivityManager.this) {
2721d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            NfcActivityState state = findResumedActivityState();
2731d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            if (state == null) return null;
2741d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly
2751d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            return state.uri;
2761d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        }
2771d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    }
2781d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    /** Callback from NFC service, usually on binder thread */
2791d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    @Override
2801d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    public String getMimeType() {
2811d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        synchronized (NfcActivityManager.this) {
2821d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            NfcActivityState state = findResumedActivityState();
2831d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            if (state == null) return null;
2841d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly
2851d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly            return state.mimeType;
2861d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly        }
2871d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    }
2881d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    /** Callback from NFC service, usually on binder thread */
2891d7e9062330a5a02247752de32a68ecbeba82783Nick Pelly    @Override
290c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    public void onNdefPushComplete() {
2918ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        NfcAdapter.OnNdefPushCompleteCallback callback;
292c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        synchronized (NfcActivityManager.this) {
2938ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcActivityState state = findResumedActivityState();
2948ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (state == null) return;
2958ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
2968ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            callback = state.onNdefPushCompleteCallback;
297c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
298c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly
2998ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        // Make callback without lock
300c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        if (callback != null) {
301c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly            callback.onNdefPushComplete(mDefaultEvent);
302c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly        }
303c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly    }
3043433a8ae5abf7c518277e2e00c141e1dec83600cMartijn Coenen
3058ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from Activity life-cycle, on main thread */
3068ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    @Override
3078ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void onActivityCreated(Activity activity, Bundle savedInstanceState) { /* NO-OP */ }
3088ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
3098ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from Activity life-cycle, on main thread */
3108ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    @Override
3118ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void onActivityStarted(Activity activity) { /* NO-OP */ }
3128ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
3138ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from Activity life-cycle, on main thread */
3148ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    @Override
3158ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void onActivityResumed(Activity activity) {
3168ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        synchronized (NfcActivityManager.this) {
3178ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcActivityState state = findActivityState(activity);
3188ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (DBG) Log.d(TAG, "onResume() for " + activity + " " + state);
3198ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (state == null) return;
3208ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            state.resumed = true;
3218ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        }
3228ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        requestNfcServiceCallback(true);
3238ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    }
3248ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
3258ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from Activity life-cycle, on main thread */
3268ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    @Override
3278ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void onActivityPaused(Activity activity) {
3288ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        synchronized (NfcActivityManager.this) {
3298ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcActivityState state = findActivityState(activity);
3308ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (DBG) Log.d(TAG, "onPause() for " + activity + " " + state);
3318ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (state == null) return;
3328ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            state.resumed = false;
3338ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        }
3348ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        requestNfcServiceCallback(false);
3358ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    }
3368ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
3378ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from Activity life-cycle, on main thread */
3388ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    @Override
3398ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void onActivityStopped(Activity activity) { /* NO-OP */ }
3408ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
3418ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from Activity life-cycle, on main thread */
3428ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    @Override
3438ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void onActivitySaveInstanceState(Activity activity, Bundle outState) { /* NO-OP */ }
3448ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly
3458ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    /** Callback from Activity life-cycle, on main thread */
3468ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    @Override
3478ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    public void onActivityDestroyed(Activity activity) {
3488ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        synchronized (NfcActivityManager.this) {
3498ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            NfcActivityState state = findActivityState(activity);
3508ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (DBG) Log.d(TAG, "onDestroy() for " + activity + " " + state);
3518ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            if (state != null) {
3528ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                // release all associated references
3538ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly                destroyActivityState(activity);
3548ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly            }
3558ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly        }
3568ce7a27770735791b5c38e4128f4ab9cee86bc43Nick Pelly    }
357c84c89a6cacaf16c1ba41f57cc1aecdb150e85f9Nick Pelly}
358