/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.nfc.cardemulation;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.nfc.cardemulation.NfcFServiceInfo;
import android.nfc.cardemulation.NfcFCardEmulation;
import android.nfc.cardemulation.HostNfcFService;
import android.os.UserHandle;
import android.util.AtomicFile;
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;

import com.android.internal.util.FastXmlSerializer;
import com.google.android.collect.Maps;


import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import android.os.SystemProperties;

public class RegisteredNfcFServicesCache {
    static final String XML_INDENT_OUTPUT_FEATURE = "http://xmlpull.org/v1/doc/features.html#indent-output";
    static final String TAG = "RegisteredNfcFServicesCache";
    static final boolean DBG = ((SystemProperties.get("persist.nfc.ce_debug").equals("1")) ? true : false);

    final Context mContext;
    final AtomicReference<BroadcastReceiver> mReceiver;

    final Object mLock = new Object();
    // All variables below synchronized on mLock

    // mUserServices holds the card emulation services that are running for each user
    final SparseArray<UserServices> mUserServices = new SparseArray<UserServices>();
    final Callback mCallback;
    final AtomicFile mDynamicSystemCodeNfcid2File;
    boolean mActivated = false;
    boolean mUserSwitched = false;

    public interface Callback {
        void onNfcFServicesUpdated(int userId, final List<NfcFServiceInfo> services);
    };

    static class DynamicSystemCode {
        public final int uid;
        public final String systemCode;

        DynamicSystemCode(int uid, String systemCode) {
            this.uid = uid;
            this.systemCode = systemCode;
        }
    };

    static class DynamicNfcid2 {
        public final int uid;
        public final String nfcid2;

        DynamicNfcid2(int uid, String nfcid2) {
            this.uid = uid;
            this.nfcid2 = nfcid2;
        }
    };

    private static class UserServices {
        /**
         * All services that have registered
         */
        final HashMap<ComponentName, NfcFServiceInfo> services =
                Maps.newHashMap(); // Re-built at run-time
        final HashMap<ComponentName, DynamicSystemCode> dynamicSystemCode =
                Maps.newHashMap(); // In memory cache of dynamic System Code store
        final HashMap<ComponentName, DynamicNfcid2> dynamicNfcid2 =
                Maps.newHashMap(); // In memory cache of dynamic NFCID2 store
    };

    private UserServices findOrCreateUserLocked(int userId) {
        UserServices userServices = mUserServices.get(userId);
        if (userServices == null) {
            userServices = new UserServices();
            mUserServices.put(userId, userServices);
        }
        return userServices;
    }

    public RegisteredNfcFServicesCache(Context context, Callback callback) {
        mContext = context;
        mCallback = callback;

        final BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
                String action = intent.getAction();
                if (DBG) Log.d(TAG, "Intent action: " + action);
                if (uid != -1) {
                    boolean replaced = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) &&
                            (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
                             Intent.ACTION_PACKAGE_REMOVED.equals(action));
                    if (!replaced) {
                        int currentUser = ActivityManager.getCurrentUser();
                        if (currentUser == UserHandle.getUserId(uid)) {
                            invalidateCache(UserHandle.getUserId(uid));
                        } else {
                            // Cache will automatically be updated on user switch
                        }
                    } else {
                        if (DBG) Log.d(TAG,
                                "Ignoring package intent due to package being replaced.");
                    }
                }
            }
        };
        mReceiver = new AtomicReference<BroadcastReceiver>(receiver);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_FIRST_LAUNCH);
        intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
        intentFilter.addDataScheme("package");
        mContext.registerReceiverAsUser(mReceiver.get(), UserHandle.ALL, intentFilter, null, null);

        // Register for events related to sdcard operations
        IntentFilter sdFilter = new IntentFilter();
        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
        mContext.registerReceiverAsUser(mReceiver.get(), UserHandle.ALL, sdFilter, null, null);

        File dataDir = mContext.getFilesDir();
        mDynamicSystemCodeNfcid2File =
                new AtomicFile(new File(dataDir, "dynamic_systemcode_nfcid2.xml"));
    }

    void initialize() {
        synchronized (mLock) {
            readDynamicSystemCodeNfcid2Locked();
        }
        invalidateCache(ActivityManager.getCurrentUser());
    }

    void dump(ArrayList<NfcFServiceInfo> services) {
        for (NfcFServiceInfo service : services) {
            Log.d(TAG, service.toString());
        }
    }

    boolean containsServiceLocked(ArrayList<NfcFServiceInfo> services,
            ComponentName componentName) {
        for (NfcFServiceInfo service : services) {
            if (service.getComponent().equals(componentName)) return true;
        }
        return false;
    }

    public boolean hasService(int userId, ComponentName componentName) {
        return getService(userId, componentName) != null;
    }

    public NfcFServiceInfo getService(int userId, ComponentName componentName) {
        synchronized (mLock) {
            UserServices userServices = findOrCreateUserLocked(userId);
            return userServices.services.get(componentName);
        }
    }

    public List<NfcFServiceInfo> getServices(int userId) {
        final ArrayList<NfcFServiceInfo> services = new ArrayList<NfcFServiceInfo>();
        synchronized (mLock) {
            UserServices userServices = findOrCreateUserLocked(userId);
            services.addAll(userServices.services.values());
        }
        return services;
    }

    ArrayList<NfcFServiceInfo> getInstalledServices(int userId) {
        if (DBG) Log.d(TAG, "getInstalledServices");
        PackageManager pm;
        try {
            pm = mContext.createPackageContextAsUser("android", 0,
                    new UserHandle(userId)).getPackageManager();
        } catch (NameNotFoundException e) {
            Log.e(TAG, "Could not create user package context");
            return null;
        }

        ArrayList<NfcFServiceInfo> validServices = new ArrayList<NfcFServiceInfo>();

        List<ResolveInfo> resolvedServices = pm.queryIntentServicesAsUser(
                new Intent(HostNfcFService.SERVICE_INTERFACE),
                PackageManager.GET_META_DATA, userId);

        for (ResolveInfo resolvedService : resolvedServices) {
            try {
                ServiceInfo si = resolvedService.serviceInfo;
                ComponentName componentName = new ComponentName(si.packageName, si.name);
                // Check if the package holds the NFC permission
                if (pm.checkPermission(android.Manifest.permission.NFC, si.packageName) !=
                        PackageManager.PERMISSION_GRANTED) {
                    Log.e(TAG, "Skipping NfcF service " + componentName +
                            ": it does not require the permission " +
                            android.Manifest.permission.NFC);
                    continue;
                }
                if (!android.Manifest.permission.BIND_NFC_SERVICE.equals(
                        si.permission)) {
                    Log.e(TAG, "Skipping NfcF service " + componentName +
                            ": it does not require the permission " +
                            android.Manifest.permission.BIND_NFC_SERVICE);
                    continue;
                }
                NfcFServiceInfo service = new NfcFServiceInfo(pm, resolvedService);
                if (service != null) {
                    validServices.add(service);
                }
            } catch (XmlPullParserException e) {
                Log.w(TAG, "Unable to load component info " + resolvedService.toString(), e);
            } catch (IOException e) {
                Log.w(TAG, "Unable to load component info " + resolvedService.toString(), e);
            }
        }

        return validServices;
    }

    public void invalidateCache(int userId) {
        if (DBG) Log.d(TAG, "invalidateCache");
        final ArrayList<NfcFServiceInfo> validServices = getInstalledServices(userId);
        if (validServices == null) {
            return;
        }
        ArrayList<NfcFServiceInfo> newServices = null;
        synchronized (mLock) {
            UserServices userServices = findOrCreateUserLocked(userId);

            // Check update
            ArrayList<NfcFServiceInfo> cachedServices =
                    new ArrayList<NfcFServiceInfo>(userServices.services.values());
            ArrayList<NfcFServiceInfo> toBeAdded = new ArrayList<NfcFServiceInfo>();
            ArrayList<NfcFServiceInfo> toBeRemoved = new ArrayList<NfcFServiceInfo>();
            boolean matched = false;
            for (NfcFServiceInfo validService : validServices) {
                for (NfcFServiceInfo cachedService : cachedServices) {
                    if (validService.equals(cachedService)) {
                        matched = true;
                        break;
                    }
                }
                if (!matched) {
                    toBeAdded.add(validService);
                }
                matched = false;
            }
            for (NfcFServiceInfo cachedService : cachedServices) {
                for (NfcFServiceInfo validService : validServices) {
                    if (cachedService.equals(validService)) {
                        matched = true;
                        break;
                    }
                }
                if (!matched) {
                    toBeRemoved.add(cachedService);
                }
                matched = false;
            }
            if (mUserSwitched) {
                Log.d(TAG, "User switched, rebuild internal cache");
                mUserSwitched = false;
            } else if (toBeAdded.size() == 0 && toBeRemoved.size() == 0) {
                Log.d(TAG, "Service unchanged, not updating");
                return;
            }

            // Update cache
            for (NfcFServiceInfo service : toBeAdded) {
                userServices.services.put(service.getComponent(), service);
                if (DBG) Log.d(TAG, "Added service: " + service.getComponent());
            }
            for (NfcFServiceInfo service : toBeRemoved) {
                userServices.services.remove(service.getComponent());
                if (DBG) Log.d(TAG, "Removed service: " + service.getComponent());
            }
            // Apply dynamic System Code mappings
            ArrayList<ComponentName> toBeRemovedDynamicSystemCode =
                    new ArrayList<ComponentName>();
            for (Map.Entry<ComponentName, DynamicSystemCode> entry :
                    userServices.dynamicSystemCode.entrySet()) {
                // Verify component / uid match
                ComponentName componentName = entry.getKey();
                DynamicSystemCode dynamicSystemCode = entry.getValue();
                NfcFServiceInfo service = userServices.services.get(componentName);
                if (service == null || (service.getUid() != dynamicSystemCode.uid)) {
                    toBeRemovedDynamicSystemCode.add(componentName);
                    continue;
                } else {
                    service.setOrReplaceDynamicSystemCode(dynamicSystemCode.systemCode);
                }
            }
            // Apply dynamic NFCID2 mappings
            ArrayList<ComponentName> toBeRemovedDynamicNfcid2 =
                    new ArrayList<ComponentName>();
            for (Map.Entry<ComponentName, DynamicNfcid2> entry :
                    userServices.dynamicNfcid2.entrySet()) {
                // Verify component / uid match
                ComponentName componentName = entry.getKey();
                DynamicNfcid2 dynamicNfcid2 = entry.getValue();
                NfcFServiceInfo service = userServices.services.get(componentName);
                if (service == null || (service.getUid() != dynamicNfcid2.uid)) {
                    toBeRemovedDynamicNfcid2.add(componentName);
                    continue;
                } else {
                    service.setOrReplaceDynamicNfcid2(dynamicNfcid2.nfcid2);
                }
            }
            for (ComponentName removedComponent : toBeRemovedDynamicSystemCode) {
                Log.d(TAG, "Removing dynamic System Code registered by " +
                        removedComponent);
                userServices.dynamicSystemCode.remove(removedComponent);
            }
            for (ComponentName removedComponent : toBeRemovedDynamicNfcid2) {
                Log.d(TAG, "Removing dynamic NFCID2 registered by " +
                        removedComponent);
                userServices.dynamicNfcid2.remove(removedComponent);
            }
            // Assign a NFCID2 for services requesting a random NFCID2, then apply
            boolean nfcid2Assigned = false;
            for (Map.Entry<ComponentName, NfcFServiceInfo> entry :
                userServices.services.entrySet()) {
                NfcFServiceInfo service = entry.getValue();
                if (service.getNfcid2().equalsIgnoreCase("RANDOM")) {
                    String randomNfcid2 = generateRandomNfcid2();
                    service.setOrReplaceDynamicNfcid2(randomNfcid2);
                    DynamicNfcid2 dynamicNfcid2 =
                            new DynamicNfcid2(service.getUid(), randomNfcid2);
                    userServices.dynamicNfcid2.put(entry.getKey(), dynamicNfcid2);
                    nfcid2Assigned = true;
                }
            }

            // Persist to filesystem
            if (toBeRemovedDynamicSystemCode.size() > 0 ||
                    toBeRemovedDynamicNfcid2.size() > 0 ||
                    nfcid2Assigned) {
                writeDynamicSystemCodeNfcid2Locked();
            }

            newServices = new ArrayList<NfcFServiceInfo>(userServices.services.values());
        }
        mCallback.onNfcFServicesUpdated(userId, Collections.unmodifiableList(newServices));
        if (DBG) dump(newServices);
    }

    private void readDynamicSystemCodeNfcid2Locked() {
        if (DBG) Log.d(TAG, "readDynamicSystemCodeNfcid2Locked");
        FileInputStream fis = null;
        try {
            if (!mDynamicSystemCodeNfcid2File.getBaseFile().exists()) {
                Log.d(TAG, "Dynamic System Code, NFCID2 file does not exist.");
                return;
            }
            fis = mDynamicSystemCodeNfcid2File.openRead();
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(fis, null);
            int eventType = parser.getEventType();
            while (eventType != XmlPullParser.START_TAG &&
                    eventType != XmlPullParser.END_DOCUMENT) {
                eventType = parser.next();
            }
            String tagName = parser.getName();
            if ("services".equals(tagName)) {
                ComponentName componentName = null;
                int currentUid = -1;
                String systemCode = null;
                String nfcid2 = null;
                String description = null;
                while (eventType != XmlPullParser.END_DOCUMENT) {
                    tagName = parser.getName();
                    if (eventType == XmlPullParser.START_TAG) {
                        if ("service".equals(tagName) && parser.getDepth() == 2) {
                            String compString =
                                    parser.getAttributeValue(null, "component");
                            String uidString =
                                    parser.getAttributeValue(null, "uid");
                            String systemCodeString =
                                    parser.getAttributeValue(null, "system-code");
                            String descriptionString =
                                    parser.getAttributeValue(null, "description");
                            String nfcid2String =
                                    parser.getAttributeValue(null, "nfcid2");
                            if (compString == null || uidString == null) {
                                Log.e(TAG, "Invalid service attributes");
                            } else {
                                try {
                                    componentName = ComponentName.unflattenFromString(compString);
                                    currentUid = Integer.parseInt(uidString);
                                    systemCode = systemCodeString;
                                    description = descriptionString;
                                    nfcid2 = nfcid2String;
                                } catch (NumberFormatException e) {
                                    Log.e(TAG, "Could not parse service uid");
                                }
                            }
                        }
                    } else if (eventType == XmlPullParser.END_TAG) {
                        if ("service".equals(tagName)) {
                            // See if we have a valid service
                            if (componentName != null && currentUid >= 0) {
                                final int userId = UserHandle.getUserId(currentUid);
                                UserServices userServices = findOrCreateUserLocked(userId);
                                if (systemCode != null) {
                                    DynamicSystemCode dynamicSystemCode =
                                            new DynamicSystemCode(currentUid, systemCode);
                                    userServices.dynamicSystemCode.put(
                                            componentName, dynamicSystemCode);
                                }
                                if (nfcid2 != null) {
                                    DynamicNfcid2 dynamicNfcid2 =
                                            new DynamicNfcid2(currentUid, nfcid2);
                                    userServices.dynamicNfcid2.put(
                                            componentName, dynamicNfcid2);
                                }
                            }
                            componentName = null;
                            currentUid = -1;
                            systemCode = null;
                            description = null;
                            nfcid2 = null;
                        }
                    }
                    eventType = parser.next();
                };
            }
        } catch (Exception e) {
            Log.e(TAG, "Could not parse dynamic System Code, NFCID2 file, trashing.");
            mDynamicSystemCodeNfcid2File.delete();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                }
            }
        }
    }

    private boolean writeDynamicSystemCodeNfcid2Locked() {
        if (DBG) Log.d(TAG, "writeDynamicSystemCodeNfcid2Locked");
        FileOutputStream fos = null;
        try {
            fos = mDynamicSystemCodeNfcid2File.startWrite();
            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(fos, "utf-8");
            out.startDocument(null, true);
            out.setFeature(XML_INDENT_OUTPUT_FEATURE, true);
            out.startTag(null, "services");
            for (int i = 0; i < mUserServices.size(); i++) {
                final UserServices userServices = mUserServices.valueAt(i);
                for (Map.Entry<ComponentName, DynamicSystemCode> entry :
                        userServices.dynamicSystemCode.entrySet()) {
                    out.startTag(null, "service");
                    out.attribute(null, "component", entry.getKey().flattenToString());
                    out.attribute(null, "uid", Integer.toString(entry.getValue().uid));
                    out.attribute(null, "system-code", entry.getValue().systemCode);
                    if (userServices.dynamicNfcid2.containsKey(entry.getKey())) {
                        out.attribute(null, "nfcid2",
                                userServices.dynamicNfcid2.get(entry.getKey()).nfcid2);
                    }
                    out.endTag(null, "service");
                }
                for (Map.Entry<ComponentName, DynamicNfcid2> entry :
                        userServices.dynamicNfcid2.entrySet()) {
                    if (!userServices.dynamicSystemCode.containsKey(entry.getKey())) {
                        out.startTag(null, "service");
                        out.attribute(null, "component", entry.getKey().flattenToString());
                        out.attribute(null, "uid", Integer.toString(entry.getValue().uid));
                        out.attribute(null, "nfcid2", entry.getValue().nfcid2);
                        out.endTag(null, "service");
                    }
                }
            }
            out.endTag(null, "services");
            out.endDocument();
            mDynamicSystemCodeNfcid2File.finishWrite(fos);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Error writing dynamic System Code, NFCID2", e);
            if (fos != null) {
                mDynamicSystemCodeNfcid2File.failWrite(fos);
            }
            return false;
        }
    }

    public boolean registerSystemCodeForService(int userId, int uid,
            ComponentName componentName, String systemCode) {
        if (DBG) Log.d(TAG, "registerSystemCodeForService");
        ArrayList<NfcFServiceInfo> newServices = null;
        boolean success;
        synchronized (mLock) {
            if (mActivated) {
                Log.d(TAG, "failed to register System Code during activation");
                return false;
            }
            UserServices userServices = findOrCreateUserLocked(userId);
            // Check if we can find this service
            NfcFServiceInfo service = getService(userId, componentName);
            if (service == null) {
                Log.e(TAG, "Service " + componentName + " does not exist.");
                return false;
            }
            if (service.getUid() != uid) {
                // This is probably a good indication something is wrong here.
                // Either newer service installed with different uid (but then
                // we should have known about it), or somebody calling us from
                // a different uid.
                Log.e(TAG, "UID mismatch.");
                return false;
            }
            if (!systemCode.equalsIgnoreCase("NULL") &&
                    !NfcFCardEmulation.isValidSystemCode(systemCode)) {
                Log.e(TAG, "System Code " + systemCode + " is not a valid System Code");
                return false;
            }
            // Apply dynamic System Code mappings
            systemCode = systemCode.toUpperCase();
            DynamicSystemCode oldDynamicSystemCode =
                    userServices.dynamicSystemCode.get(componentName);
            DynamicSystemCode dynamicSystemCode = new DynamicSystemCode(uid, systemCode);
            userServices.dynamicSystemCode.put(componentName, dynamicSystemCode);
            success = writeDynamicSystemCodeNfcid2Locked();
            if (success) {
                service.setOrReplaceDynamicSystemCode(systemCode);
                newServices = new ArrayList<NfcFServiceInfo>(userServices.services.values());
            } else {
                Log.e(TAG, "Failed to persist System Code.");
                // Undo registration
                if (oldDynamicSystemCode == null) {
                    userServices.dynamicSystemCode.remove(componentName);
                } else {
                    userServices.dynamicSystemCode.put(componentName, oldDynamicSystemCode);
                }
            }
        }
        if (success) {
            // Make callback without the lock held
            mCallback.onNfcFServicesUpdated(userId, newServices);
        }
        return success;
    }

    public String getSystemCodeForService(int userId, int uid, ComponentName componentName) {
        if (DBG) Log.d(TAG, "getSystemCodeForService");
        NfcFServiceInfo service = getService(userId, componentName);
        if (service != null) {
            if (service.getUid() != uid) {
                Log.e(TAG, "UID mismatch");
                return null;
            }
            return service.getSystemCode();
        } else {
            Log.e(TAG, "Could not find service " + componentName);
            return null;
        }
    }

    public boolean removeSystemCodeForService(int userId, int uid, ComponentName componentName) {
        if (DBG) Log.d(TAG, "removeSystemCodeForService");
        return registerSystemCodeForService(userId, uid, componentName, "NULL");
    }

    public boolean setNfcid2ForService(int userId, int uid,
            ComponentName componentName, String nfcid2) {
        if (DBG) Log.d(TAG, "setNfcid2ForService");
        ArrayList<NfcFServiceInfo> newServices = null;
        boolean success;
        synchronized (mLock) {
            if (mActivated) {
                Log.d(TAG, "failed to set NFCID2 during activation");
                return false;
            }
            UserServices userServices = findOrCreateUserLocked(userId);
            // Check if we can find this service
            NfcFServiceInfo service = getService(userId, componentName);
            if (service == null) {
                Log.e(TAG, "Service " + componentName + " does not exist.");
                return false;
            }
            if (service.getUid() != uid) {
                // This is probably a good indication something is wrong here.
                // Either newer service installed with different uid (but then
                // we should have known about it), or somebody calling us from
                // a different uid.
                Log.e(TAG, "UID mismatch.");
                return false;
            }
            if (!NfcFCardEmulation.isValidNfcid2(nfcid2)) {
                Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2");
                return false;
            }
            // Apply dynamic NFCID2 mappings
            nfcid2 = nfcid2.toUpperCase();
            DynamicNfcid2 oldDynamicNfcid2 = userServices.dynamicNfcid2.get(componentName);
            DynamicNfcid2 dynamicNfcid2 = new DynamicNfcid2(uid, nfcid2);
            userServices.dynamicNfcid2.put(componentName, dynamicNfcid2);
            success = writeDynamicSystemCodeNfcid2Locked();
            if (success) {
                service.setOrReplaceDynamicNfcid2(nfcid2);
                newServices = new ArrayList<NfcFServiceInfo>(userServices.services.values());
            } else {
                Log.e(TAG, "Failed to persist NFCID2.");
                // Undo registration
                if (oldDynamicNfcid2 == null) {
                    userServices.dynamicNfcid2.remove(componentName);
                } else {
                    userServices.dynamicNfcid2.put(componentName, oldDynamicNfcid2);
                }
            }
        }
        if (success) {
            // Make callback without the lock held
            mCallback.onNfcFServicesUpdated(userId, newServices);
        }
        return success;
    }

    public String getNfcid2ForService(int userId, int uid, ComponentName componentName) {
        if (DBG) Log.d(TAG, "getNfcid2ForService");
        NfcFServiceInfo service = getService(userId, componentName);
        if (service != null) {
            if (service.getUid() != uid) {
                Log.e(TAG, "UID mismatch");
                return null;
            }
            return service.getNfcid2();
        } else {
            Log.e(TAG, "Could not find service " + componentName);
            return null;
        }
    }

    public void onHostEmulationActivated() {
        if (DBG) Log.d(TAG, "onHostEmulationActivated");
        synchronized (mLock) {
            mActivated = true;
        }
    }

    public void onHostEmulationDeactivated() {
        if (DBG) Log.d(TAG, "onHostEmulationDeactivated");
        synchronized (mLock) {
            mActivated = false;
        }
    }

    public void onNfcDisabled() {
        synchronized (mLock) {
            mActivated = false;
        }
    }

    public void onUserSwitched() {
        synchronized (mLock) {
            mUserSwitched = true;
        }
    }

    private String generateRandomNfcid2() {
        long min = 0L;
        long max = 0xFFFFFFFFFFFFL;

        long randomNfcid2 = (long)Math.floor(Math.random() * (max-min+1)) + min;
        return String.format("02FE%02X%02X%02X%02X%02X%02X",
                (randomNfcid2 >>> 8 * 5) & 0xFF, (randomNfcid2 >>> 8 * 4) & 0xFF,
                (randomNfcid2 >>> 8 * 3) & 0xFF, (randomNfcid2 >>> 8 * 2) & 0xFF,
                (randomNfcid2 >>> 8 * 1) & 0xFF, (randomNfcid2 >>> 8 * 0) & 0xFF);
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Registered HCE-F services for current user: ");
        synchronized (mLock) {
            UserServices userServices = findOrCreateUserLocked(ActivityManager.getCurrentUser());
            for (NfcFServiceInfo service : userServices.services.values()) {
                service.dump(fd, pw, args);
                pw.println("");
            }
            pw.println("");
        }
    }

}
