/*
 * Copyright (C) 2013 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 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.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.ResolveInfoFlags;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.nfc.cardemulation.AidGroup;
import android.nfc.cardemulation.ApduServiceInfo;
import android.nfc.cardemulation.CardEmulation;
import android.nfc.cardemulation.HostApduService;
import android.nfc.cardemulation.OffHostApduService;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.os.UserManager;
import android.sysprop.NfcProperties;
import android.util.AtomicFile;
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.nfc.Utils;

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

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;

/**
 * This class is inspired by android.content.pm.RegisteredServicesCache
 * That class was not re-used because it doesn't support dynamically
 * registering additional properties, but generates everything from
 * the manifest. Since we have some properties that are not in the manifest,
 * it's less suited.
 */
public class RegisteredServicesCache {
    static final String XML_INDENT_OUTPUT_FEATURE = "http://xmlpull.org/v1/doc/features.html#indent-output";
    static final String TAG = "RegisteredServicesCache";
    static final boolean DEBUG = NfcProperties.debug_enabled().orElse(false);

    final Context mContext;
    final AtomicReference<BroadcastReceiver> mReceiver;

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

    // mUserHandles holds the UserHandles of all the profiles that belong to current user
    @GuardedBy("mLock")
    List<UserHandle> mUserHandles;

    // mUserServices holds the card emulation services that are running for each user
    final SparseArray<UserServices> mUserServices = new SparseArray<UserServices>();
    final Callback mCallback;
    final AtomicFile mDynamicSettingsFile;
    final AtomicFile mOthersFile;
    public interface Callback {
        /**
         * ServicesUpdated for specific userId.
         */
        void onServicesUpdated(int userId, List<ApduServiceInfo> services,
                boolean validateInstalled);
    };

    static class DynamicSettings {
        public final int uid;
        public final HashMap<String, AidGroup> aidGroups = new HashMap<>();
        public String offHostSE;
        public boolean defaultToObserveMode = false;

        DynamicSettings(int uid) {
            this.uid = uid;
        }
    };

    static class OtherServiceStatus {
        public final int uid;
        public boolean checked;

        OtherServiceStatus(int uid, boolean checked) {
            this.uid = uid;
            this.checked = checked;
        }
    };

    private static class UserServices {
        /**
         * All services that have registered
         */
        final HashMap<ComponentName, ApduServiceInfo> services =
                new HashMap<>(); // Re-built at run-time
        final HashMap<ComponentName, DynamicSettings> dynamicSettings =
                new HashMap<>(); // In memory cache of dynamic settings
        final HashMap<ComponentName, OtherServiceStatus> others =
                new HashMap<>();
    };

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

    private int getProfileParentId(int userId) {
        UserManager um = mContext.createContextAsUser(
                UserHandle.of(userId), /*flags=*/0)
                .getSystemService(UserManager.class);
        UserHandle uh = um.getProfileParent(UserHandle.of(userId));
        return uh == null ? userId : uh.getIdentifier();
    }

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

        refreshUserProfilesLocked();

        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 (DEBUG) Log.d(TAG, "Intent action: " + action);

                if (RoutingOptionManager.getInstance().isRoutingTableOverrided()) {
                    if (DEBUG) Log.d(TAG, "Routing table overrided. Skip invalidateCache()");
                }

                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 == getProfileParentId(UserHandle.
                                getUserHandleForUid(uid).getIdentifier())) {
                            if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
                                invalidateCache(UserHandle.
                                        getUserHandleForUid(uid).getIdentifier(), true);
                            } else {
                                invalidateCache(UserHandle.
                                        getUserHandleForUid(uid).getIdentifier(), false);
                            }
                        } else {
                            // Cache will automatically be updated on user switch
                        }
                    } else {
                        if (DEBUG) 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.registerReceiverForAllUsers(mReceiver.get(), 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.registerReceiverForAllUsers(mReceiver.get(), sdFilter, null, null);

        File dataDir = mContext.getFilesDir();
        mDynamicSettingsFile = new AtomicFile(new File(dataDir, "dynamic_aids.xml"));
        mOthersFile = new AtomicFile(new File(dataDir, "other_status.xml"));
    }

    void initialize() {
        synchronized (mLock) {
            readDynamicSettingsLocked();
            readOthersLocked();
            for (UserHandle uh : mUserHandles) {
                invalidateCache(uh.getIdentifier(), false);
            }
        }
    }

    public void onUserSwitched() {
        synchronized (mLock) {
            refreshUserProfilesLocked();
        }
    }

    public void onManagedProfileChanged() {
        synchronized (mLock) {
            refreshUserProfilesLocked();
        }
    }

    private void refreshUserProfilesLocked() {
        UserManager um = mContext.createContextAsUser(
                UserHandle.of(ActivityManager.getCurrentUser()), /*flags=*/0)
                .getSystemService(UserManager.class);
        mUserHandles = um.getEnabledProfiles();
        List<UserHandle> removeUserHandles = new ArrayList<UserHandle>();

        for (UserHandle uh : mUserHandles) {
            if (um.isQuietModeEnabled(uh)) {
                removeUserHandles.add(uh);
            }
        }
        mUserHandles.removeAll(removeUserHandles);
    }

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

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

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

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

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

    public List<ApduServiceInfo> getServicesForCategory(int userId, String category) {
        final ArrayList<ApduServiceInfo> services = new ArrayList<ApduServiceInfo>();
        synchronized (mLock) {
            UserServices userServices = findOrCreateUserLocked(userId);
            for (ApduServiceInfo service : userServices.services.values()) {
                if (service.hasCategory(category)) services.add(service);
            }
        }
        return services;
    }

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

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

        List<ResolveInfo> resolvedServices = new ArrayList<>(pm.queryIntentServicesAsUser(
                new Intent(HostApduService.SERVICE_INTERFACE),
                ResolveInfoFlags.of(PackageManager.GET_META_DATA), UserHandle.of(userId)));

        List<ResolveInfo> resolvedOffHostServices = pm.queryIntentServicesAsUser(
                new Intent(OffHostApduService.SERVICE_INTERFACE),
                ResolveInfoFlags.of(PackageManager.GET_META_DATA), UserHandle.of(userId));
        resolvedServices.addAll(resolvedOffHostServices);

        for (ResolveInfo resolvedService : resolvedServices) {
            try {
                boolean onHost = !resolvedOffHostServices.contains(resolvedService);
                ServiceInfo si = resolvedService.serviceInfo;
                ComponentName componentName = new ComponentName(si.packageName, si.name);
                // Check if the package exported the service in manifest
                if (!si.exported) {
                    Log.e(TAG, "Skipping application component " + componentName +
                            ": it must configured as exported");
                    continue;
                }
                // Check if the package holds the NFC permission
                if (pm.checkPermission(android.Manifest.permission.NFC, si.packageName) !=
                        PackageManager.PERMISSION_GRANTED) {
                    Log.e(TAG, "Skipping application component " + componentName +
                            ": it must request the permission " +
                            android.Manifest.permission.NFC);
                    continue;
                }
                if (!android.Manifest.permission.BIND_NFC_SERVICE.equals(
                        si.permission)) {
                    Log.e(TAG, "Skipping APDU service " + componentName +
                            ": it does not require the permission " +
                            android.Manifest.permission.BIND_NFC_SERVICE);
                    continue;
                }
                ApduServiceInfo service = new ApduServiceInfo(pm, resolvedService, onHost);
                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;
    }

    /**
     * invalidateCache for specific userId.
     */
    public void invalidateCache(int userId, boolean validateInstalled) {
        final ArrayList<ApduServiceInfo> validServices = getInstalledServices(userId);
        if (validServices == null) {
            return;
        }
        synchronized (mLock) {
            UserServices userServices = findOrCreateUserLocked(userId);

            // Find removed services
            Iterator<Map.Entry<ComponentName, ApduServiceInfo>> it =
                    userServices.services.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<ComponentName, ApduServiceInfo> entry =
                        (Map.Entry<ComponentName, ApduServiceInfo>) it.next();
                if (!containsServiceLocked(validServices, entry.getKey())) {
                    Log.d(TAG, "Service removed: " + entry.getKey());
                    it.remove();
                }
            }
            for (ApduServiceInfo service : validServices) {
                if (DEBUG) Log.d(TAG, "Adding service: " + service.getComponent() +
                        " AIDs: " + service.getAids());
                userServices.services.put(service.getComponent(), service);
            }

            // Apply dynamic settings mappings
            ArrayList<ComponentName> toBeRemoved = new ArrayList<ComponentName>();
            for (Map.Entry<ComponentName, DynamicSettings> entry :
                    userServices.dynamicSettings.entrySet()) {
                // Verify component / uid match
                ComponentName component = entry.getKey();
                DynamicSettings dynamicSettings = entry.getValue();
                ApduServiceInfo serviceInfo = userServices.services.get(component);
                if (serviceInfo == null || (serviceInfo.getUid() != dynamicSettings.uid)) {
                    toBeRemoved.add(component);
                    continue;
                } else {
                    for (AidGroup group : dynamicSettings.aidGroups.values()) {
                        serviceInfo.setDynamicAidGroup(group);
                    }
                    if (dynamicSettings.offHostSE != null) {
                        serviceInfo.setOffHostSecureElement(dynamicSettings.offHostSE);
                    }
                }
            }
            if (toBeRemoved.size() > 0) {
                for (ComponentName component : toBeRemoved) {
                    Log.d(TAG, "Removing dynamic AIDs registered by " + component);
                    userServices.dynamicSettings.remove(component);
                }
                // Persist to filesystem
                writeDynamicSettingsLocked();
            }
        }

        List<ApduServiceInfo> otherServices = getServicesForCategory(userId,
                CardEmulation.CATEGORY_OTHER);
        invalidateOther(userId, otherServices);

        mCallback.onServicesUpdated(userId, Collections.unmodifiableList(validServices),
                validateInstalled);
        dump(validServices);
    }

    private void invalidateOther(int userId, List<ApduServiceInfo> validOtherServices) {
        Log.d(TAG, "invalidate : " + userId);
        // remove services
        synchronized (mLock) {
            UserServices userServices = findOrCreateUserLocked(userId);
            boolean needToWrite = false;
            Iterator<Map.Entry<ComponentName, OtherServiceStatus>> it =
                    userServices.others.entrySet().iterator();

            while (it.hasNext()) {
                Map.Entry<ComponentName, OtherServiceStatus> entry = it.next();
                if (!containsServiceLocked((ArrayList<ApduServiceInfo>) validOtherServices,
                        entry.getKey())) {
                    Log.d(TAG, "Service removed: " + entry.getKey());
                    needToWrite = true;
                    it.remove();
                }
            }

            UserManager um = mContext.createContextAsUser(
                            UserHandle.of(ActivityManager.getCurrentUser()), /*flags=*/0)
                    .getSystemService(UserManager.class);
            boolean isManagedProfile = um.isManagedProfile(userId);
            Log.i(TAG, "current user: " + ActivityManager.getCurrentUser() +
                    ", is managed profile : " + isManagedProfile );
            boolean isChecked = !(isManagedProfile);
            // TODO: b/313040065 temperatory set isChecked always true due to there's no UI in AOSP
            isChecked = true;

            for (ApduServiceInfo service : validOtherServices) {
                Log.d(TAG, "update valid otherService: " + service.getComponent()
                        + " AIDs: " + service.getAids());
                if (!service.hasCategory(CardEmulation.CATEGORY_OTHER)) {
                    Log.e(TAG, "service does not have other category");
                    continue;
                }

                ComponentName component = service.getComponent();
                OtherServiceStatus status = userServices.others.get(component);

                if (status == null) {
                    Log.d(TAG, "New other service");
                    status = new OtherServiceStatus(service.getUid(), isChecked);
                    needToWrite = true;
                } else {
                    Log.d(TAG, "Existed other service");
                }
                service.setCategoryOtherServiceEnabled(status.checked);
                userServices.others.put(component, status);
            }

            if (needToWrite) {
                writeOthersLocked();
            }
        }
    }
    private void readDynamicSettingsLocked() {
        FileInputStream fis = null;
        try {
            if (!mDynamicSettingsFile.getBaseFile().exists()) {
                Log.d(TAG, "Dynamic AIDs file does not exist.");
                return;
            }
            fis = mDynamicSettingsFile.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)) {
                boolean inService = false;
                ComponentName currentComponent = null;
                int currentUid = -1;
                String currentOffHostSE = null;
                boolean defaultToObserveMode = false;
                ArrayList<AidGroup> currentGroups = new ArrayList<AidGroup>();
                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 offHostString = parser.getAttributeValue(null, "offHostSE");
                            String defaultToObserveModeStr =
                                parser.getAttributeValue(null, "defaultToObserveMode");
                            if (compString == null || uidString == null) {
                                Log.e(TAG, "Invalid service attributes");
                            } else {
                                try {
                                    currentUid = Integer.parseInt(uidString);
                                    currentComponent = ComponentName.unflattenFromString(compString);
                                    currentOffHostSE = offHostString;
                                    inService = true;
                                    defaultToObserveMode =
                                        XmlUtils.convertValueToBoolean(defaultToObserveModeStr,
                                        false);
                                } catch (NumberFormatException e) {
                                    Log.e(TAG, "Could not parse service uid");
                                }
                            }
                        }
                        if ("aid-group".equals(tagName) && parser.getDepth() == 3 && inService) {
                            AidGroup group = AidGroup.createFromXml(parser);
                            if (group != null) {
                                currentGroups.add(group);
                            } else {
                                Log.e(TAG, "Could not parse AID group.");
                            }
                        }
                    } else if (eventType == XmlPullParser.END_TAG) {
                        if ("service".equals(tagName)) {
                            // See if we have a valid service
                            if (currentComponent != null && currentUid >= 0 &&
                                    (currentGroups.size() > 0 || currentOffHostSE != null)) {
                                final int userId = UserHandle.
                                        getUserHandleForUid(currentUid).getIdentifier();
                                DynamicSettings dynSettings = new DynamicSettings(currentUid);
                                for (AidGroup group : currentGroups) {
                                    dynSettings.aidGroups.put(group.getCategory(), group);
                                }
                                dynSettings.offHostSE = currentOffHostSE;
                                dynSettings.defaultToObserveMode = defaultToObserveMode;
                                UserServices services = findOrCreateUserLocked(userId);
                                services.dynamicSettings.put(currentComponent, dynSettings);
                            }
                            currentUid = -1;
                            currentComponent = null;
                            currentGroups.clear();
                            inService = false;
                            currentOffHostSE = null;
                        }
                    }
                    eventType = parser.next();
                };
            }
        } catch (Exception e) {
            Log.e(TAG, "Could not parse dynamic AIDs file, trashing.");
            mDynamicSettingsFile.delete();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                }
            }
        }
    }

    private void readOthersLocked() {
        Log.d(TAG, "read others locked");

        FileInputStream fis = null;
        try {
            if (!mOthersFile.getBaseFile().exists()) {
                Log.d(TAG, "Dynamic AIDs file does not exist.");
                return;
            }
            fis = mOthersFile.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)) {
                boolean checked = false;
                ComponentName currentComponent = null;
                int currentUid = -1;

                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 checkedString = parser.getAttributeValue(null, "checked");
                            if (compString == null || uidString == null || checkedString == null) {
                                Log.e(TAG, "Invalid service attributes");
                            } else {
                                try {
                                    currentUid = Integer.parseInt(uidString);
                                    currentComponent =
                                            ComponentName.unflattenFromString(compString);
                                    checked = checkedString.equals("true") ? true : false;
                                } 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 (currentComponent != null && currentUid >= 0) {
                                Log.d(TAG, " end of service tag");
                                final int userId = UserHandle.getUserId(currentUid);
                                OtherServiceStatus status =
                                        new OtherServiceStatus(currentUid, checked);
                                Log.d(TAG, " ## user id - " + userId);
                                UserServices services = findOrCreateUserLocked(userId);
                                services.others.put(currentComponent, status);
                            }
                            currentUid = -1;
                            currentComponent = null;
                            checked = false;
                        }
                    }
                    eventType = parser.next();
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "Could not parse others AIDs file, trashing.");
            mOthersFile.delete();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    // It is safe to ignore I/O exceptions when closing FileInputStream
                }
            }
        }
    }
    private boolean writeDynamicSettingsLocked() {
        FileOutputStream fos = null;
        try {
            fos = mDynamicSettingsFile.startWrite();
            XmlSerializer out = Xml.newSerializer();
            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 user = mUserServices.valueAt(i);
                for (Map.Entry<ComponentName, DynamicSettings> service :
                        user.dynamicSettings.entrySet()) {
                    out.startTag(null, "service");
                    out.attribute(null, "component", service.getKey().flattenToString());
                    out.attribute(null, "uid", Integer.toString(service.getValue().uid));
                    if(service.getValue().offHostSE != null) {
                        out.attribute(null, "offHostSE", service.getValue().offHostSE);
                    }
                    out.attribute(null,"defaultToObserveMode",
                        Boolean.toString(service.getValue().defaultToObserveMode));
                    for (AidGroup group : service.getValue().aidGroups.values()) {
                        group.writeAsXml(out);
                    }
                    out.endTag(null, "service");
                }
            }
            out.endTag(null, "services");
            out.endDocument();
            mDynamicSettingsFile.finishWrite(fos);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Error writing dynamic AIDs", e);
            if (fos != null) {
                mDynamicSettingsFile.failWrite(fos);
            }
            return false;
        }
    }

    private boolean writeOthersLocked() {
        Log.d(TAG, "write Others Locked()");

        FileOutputStream fos = null;
        try {
            fos = mOthersFile.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");

            Log.d(TAG, "userServices.size: " + mUserServices.size());
            for (int i = 0; i < mUserServices.size(); i++) {
                final UserServices user = mUserServices.valueAt(i);
                int userId = mUserServices.keyAt(i);
                // Checking for 1 times
                Log.d(TAG, "userId: " + userId);
                Log.d(TAG, "others size: " + user.others.size());
                ArrayList<ComponentName> currentService = new ArrayList<ComponentName>();
                for (Map.Entry<ComponentName, OtherServiceStatus> service :
                        user.others.entrySet()) {
                    Log.d(TAG, "component: " + service.getKey().flattenToString() +
                            ", checked: " + service.getValue().checked);

                    boolean hasDupe = false;
                    for (ComponentName cn : currentService) {
                        if (cn.equals(service.getKey())) {
                            hasDupe = true;
                            break;
                        }
                    }
                    if (hasDupe) {
                        continue;
                    } else {
                        Log.d(TAG, "Already written.");
                        currentService.add(service.getKey());
                    }

                    out.startTag(null, "service");
                    out.attribute(null, "component", service.getKey().flattenToString());
                    out.attribute(null, "uid", Integer.toString(service.getValue().uid));
                    out.attribute(null, "checked", Boolean.toString(service.getValue().checked));
                    out.endTag(null, "service");
                }
            }
            out.endTag(null, "services");
            out.endDocument();
            mOthersFile.finishWrite(fos);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Error writing dynamic AIDs", e);
            if (fos != null) {
                mOthersFile.failWrite(fos);
            }
            return false;
        }
    }

    public boolean setOffHostSecureElement(int userId, int uid, ComponentName componentName,
            String offHostSE) {
        ArrayList<ApduServiceInfo> newServices = null;
        synchronized (mLock) {
            UserServices services = findOrCreateUserLocked(userId);
            // Check if we can find this service
            ApduServiceInfo serviceInfo = getService(userId, componentName);
            if (serviceInfo == null) {
                Log.e(TAG, "Service " + componentName + " does not exist.");
                return false;
            }
            if (serviceInfo.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 (offHostSE == null || serviceInfo.isOnHost()) {
                Log.e(TAG, "OffHostSE mismatch with Service type");
                return false;
            }

            DynamicSettings dynSettings = services.dynamicSettings.get(componentName);
            if (dynSettings == null) {
                dynSettings = new DynamicSettings(uid);
            }
            dynSettings.offHostSE = offHostSE;
            boolean success = writeDynamicSettingsLocked();
            if (!success) {
                Log.e(TAG, "Failed to persist AID group.");
                dynSettings.offHostSE = null;
                return false;
            }

            serviceInfo.setOffHostSecureElement(offHostSE);
            newServices = new ArrayList<ApduServiceInfo>(services.services.values());
        }
        // Make callback without the lock held
        mCallback.onServicesUpdated(userId, newServices, true);
        return true;
    }

    public boolean resetOffHostSecureElement(int userId, int uid, ComponentName componentName) {
        ArrayList<ApduServiceInfo> newServices = null;
        synchronized (mLock) {
            UserServices services = findOrCreateUserLocked(userId);
            // Check if we can find this service
            ApduServiceInfo serviceInfo = getService(userId, componentName);
            if (serviceInfo == null) {
                Log.e(TAG, "Service " + componentName + " does not exist.");
                return false;
            }
            if (serviceInfo.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 (serviceInfo.isOnHost() || serviceInfo.getOffHostSecureElement() == null) {
                Log.e(TAG, "OffHostSE is not set");
                return false;
            }

            DynamicSettings dynSettings = services.dynamicSettings.get(componentName);
            String offHostSE = dynSettings.offHostSE;
            dynSettings.offHostSE = null;
            boolean success = writeDynamicSettingsLocked();
            if (!success) {
                Log.e(TAG, "Failed to persist AID group.");
                dynSettings.offHostSE = offHostSE;
                return false;
            }

            serviceInfo.resetOffHostSecureElement();
            newServices = new ArrayList<ApduServiceInfo>(services.services.values());
        }
        // Make callback without the lock held
        mCallback.onServicesUpdated(userId, newServices, true);
        return true;
    }

    public boolean setServiceObserveModeDefault(int userId, int uid,
            ComponentName componentName, boolean enable) {
        synchronized (mLock) {
            UserServices services = findOrCreateUserLocked(userId);
            // Check if we can find this service
            ApduServiceInfo serviceInfo = getService(userId, componentName);
            if (serviceInfo == null) {
                Log.e(TAG, "Service " + componentName + " does not exist.");
                return false;
            }
            if (serviceInfo.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;
            }
            DynamicSettings dynSettings = services.dynamicSettings.get(componentName);
            if (dynSettings == null) {
                dynSettings = new DynamicSettings(uid);
                dynSettings.offHostSE = null;
                services.dynamicSettings.put(componentName, dynSettings);
            }
            dynSettings.defaultToObserveMode = enable;
        }
        return true;
    }

    public boolean registerAidGroupForService(int userId, int uid,
            ComponentName componentName, AidGroup aidGroup) {
        ArrayList<ApduServiceInfo> newServices = null;
        boolean success;
        synchronized (mLock) {
            UserServices services = findOrCreateUserLocked(userId);
            // Check if we can find this service
            ApduServiceInfo serviceInfo = getService(userId, componentName);
            if (serviceInfo == null) {
                Log.e(TAG, "Service " + componentName + " does not exist.");
                return false;
            }
            if (serviceInfo.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;
            }
            // Do another AID validation, since a caller could have thrown in a
            // modified AidGroup object with invalid AIDs over Binder.
            List<String> aids = aidGroup.getAids();
            for (String aid : aids) {
                if (!CardEmulation.isValidAid(aid)) {
                    Log.e(TAG, "AID " + aid + " is not a valid AID");
                    return false;
                }
            }
            serviceInfo.setDynamicAidGroup(aidGroup);
            DynamicSettings dynSettings = services.dynamicSettings.get(componentName);
            if (dynSettings == null) {
                dynSettings = new DynamicSettings(uid);
                dynSettings.offHostSE = null;
                services.dynamicSettings.put(componentName, dynSettings);
            }
            dynSettings.aidGroups.put(aidGroup.getCategory(), aidGroup);
            success = writeDynamicSettingsLocked();
            if (success) {
                newServices =
                    new ArrayList<ApduServiceInfo>(services.services.values());
            } else {
                Log.e(TAG, "Failed to persist AID group.");
                // Undo registration
                dynSettings.aidGroups.remove(aidGroup.getCategory());
            }
        }
        if (success) {
            // Make callback without the lock held
            mCallback.onServicesUpdated(userId, newServices, true);
        }
        return success;
    }

    public boolean registerOtherForService(int userId,
            ComponentName componentName, boolean checked) {
        if (DEBUG) Log.d(TAG, "[register other] checked:" + checked + ", "  + componentName);

        ArrayList<ApduServiceInfo> newServices = null;
        boolean success = false;

        synchronized (mLock) {

            Log.d(TAG, "registerOtherForService / ComponentName" + componentName);
            ApduServiceInfo serviceInfo = getService(userId, componentName);

            if (serviceInfo == null) {
                Log.e(TAG, "Service " + componentName + "does not exist");
                return false;
            }

            success = updateOtherServiceStatus(userId, serviceInfo, checked);

            if (success) {
                UserServices userService = findOrCreateUserLocked(userId);
                newServices = new ArrayList<ApduServiceInfo>(userService.services.values());
            } else {
                Log.e(TAG, "Fail to other checked");
            }
        }

        if (success) {
            if (DEBUG) Log.d(TAG, "other list update due to User Select " + componentName);
            mCallback.onServicesUpdated(userId, Collections.unmodifiableList(newServices),false);
        }

        return success;
    }

    public AidGroup getAidGroupForService(int userId, int uid, ComponentName componentName,
            String category) {
        ApduServiceInfo serviceInfo = getService(userId, componentName);
        if (serviceInfo != null) {
            if (serviceInfo.getUid() != uid) {
                Log.e(TAG, "UID mismatch");
                return null;
            }
            return serviceInfo.getDynamicAidGroupForCategory(category);
        } else {
            Log.e(TAG, "Could not find service " + componentName);
            return null;
        }
    }

    public boolean removeAidGroupForService(int userId, int uid, ComponentName componentName,
            String category) {
        boolean success = false;
        ArrayList<ApduServiceInfo> newServices = null;
        synchronized (mLock) {
            UserServices services = findOrCreateUserLocked(userId);
            ApduServiceInfo serviceInfo = getService(userId, componentName);
            if (serviceInfo != null) {
                if (serviceInfo.getUid() != uid) {
                    // Calling from different uid
                    Log.e(TAG, "UID mismatch");
                    return false;
                }
                if (!serviceInfo.removeDynamicAidGroupForCategory(category)) {
                    Log.e(TAG," Could not find dynamic AIDs for category " + category);
                    return false;
                }
                // Remove from local cache
                DynamicSettings dynSettings = services.dynamicSettings.get(componentName);
                if (dynSettings != null) {
                    AidGroup deletedGroup = dynSettings.aidGroups.remove(category);
                    success = writeDynamicSettingsLocked();
                    if (success) {
                        newServices = new ArrayList<ApduServiceInfo>(services.services.values());
                    } else {
                        Log.e(TAG, "Could not persist deleted AID group.");
                        dynSettings.aidGroups.put(category, deletedGroup);
                        return false;
                    }
                } else {
                    Log.e(TAG, "Could not find aid group in local cache.");
                }
            } else {
                Log.e(TAG, "Service " + componentName + " does not exist.");
            }
        }
        if (success) {
            mCallback.onServicesUpdated(userId, newServices, true);
        }
        return success;
    }

    boolean doesServiceDefaultToObserveMode(int userId, ComponentName service) {
        UserServices services = findOrCreateUserLocked(userId);
        DynamicSettings dynSettings = services.dynamicSettings.get(service);
        return dynSettings != null && dynSettings.defaultToObserveMode;
    }

    private boolean updateOtherServiceStatus(int userId, ApduServiceInfo service, boolean checked) {
        UserServices userServices = findOrCreateUserLocked(userId);

        OtherServiceStatus status = userServices.others.get(service.getComponent());
        // This is Error handling code if otherServiceStatus is null
        if (status == null) {
            Log.d(TAG, service.getComponent() + " status is could not be null");
            return false;
        }

        if (service.isCategoryOtherServiceEnabled() == checked) {
            Log.d(TAG, "already same status: " + checked);
            return false;
        }

        service.setCategoryOtherServiceEnabled(checked);
        status.checked = checked;

        return writeOthersLocked();
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("Registered HCE services for current user: ");
        ParcelFileDescriptor pFd;
        try {
            pFd = ParcelFileDescriptor.dup(fd);
            synchronized (mLock) {
                for (UserHandle uh : mUserHandles) {
                    UserManager um = mContext.createContextAsUser(
                            uh, /*flags=*/0).getSystemService(UserManager.class);
                    pw.println("User " + Utils.maskSubstring(um.getUserName(), 3));
                    UserServices userServices = findOrCreateUserLocked(uh.getIdentifier());
                    for (ApduServiceInfo service : userServices.services.values()) {
                        service.dump(pFd, pw, args);
                        pw.println("");
                    }
                    pw.println("");
                }
            }
            pFd.close();
        } catch (IOException e) {
            pw.println("Failed to dump HCE services: " + e);
        }
    }

    /**
     * Dump debugging information as a RegisteredServicesCacheProto
     *
     * Note:
     * See proto definition in frameworks/base/core/proto/android/nfc/card_emulation.proto
     * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and
     * {@link ProtoOutputStream#end(long)} after.
     * Never reuse a proto field number. When removing a field, mark it as reserved.
     */
    void dumpDebug(ProtoOutputStream proto) {
        UserServices userServices = findOrCreateUserLocked(ActivityManager.getCurrentUser());
        for (ApduServiceInfo service : userServices.services.values()) {
            long token = proto.start(RegisteredServicesCacheProto.APDU_SERVICE_INFOS);
            service.dumpDebug(proto);
            proto.end(token);
        }
    }
}
