NFC_NCIHALx_AR0F.3.5.0_L_OpnSrc
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
new file mode 100644
index 0000000..c4494c4
--- /dev/null
+++ b/src/com/android/nfc/NfcService.java
@@ -0,0 +1,5148 @@
+ /*
+ * Copyright (C) 2010 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.
+ */
+/******************************************************************************
+ *
+ * The original Work has been changed by NXP Semiconductors.
+ *
+ * Copyright (C) 2015 NXP Semiconductors
+ *
+ * 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;
+
+import android.app.ActivityManager;
+import android.app.Application;
+import android.app.KeyguardManager;
+import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.content.res.Resources.NotFoundException;
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.net.Uri;
+import android.nfc.BeamShareData;
+import android.nfc.ErrorCodes;
+import android.nfc.FormatException;
+import android.nfc.IAppCallback;
+import android.nfc.INfcAdapter;
+import android.nfc.INfcAdapterExtras;
+import android.nfc.INfcCardEmulation;
+import android.nfc.INfcTag;
+import android.nfc.INfcUnlockHandler;
+import android.nfc.NdefMessage;
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.nfc.TechListParcel;
+import android.nfc.TransceiveResult;
+import android.nfc.tech.Ndef;
+import android.nfc.tech.TagTechnology;
+import android.os.AsyncTask;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.nfc.DeviceHost.DeviceHostListener;
+import com.android.nfc.DeviceHost.LlcpConnectionlessSocket;
+import com.android.nfc.DeviceHost.LlcpServerSocket;
+import com.android.nfc.DeviceHost.LlcpSocket;
+import com.android.nfc.DeviceHost.NfcDepEndpoint;
+import com.android.nfc.DeviceHost.TagEndpoint;
+
+import com.android.nfc.dhimpl.NativeNfcSecureElement;
+import com.android.nfc.dhimpl.NativeNfcAla;
+import java.security.MessageDigest;
+
+import android.widget.Toast;
+
+import com.android.nfc.cardemulation.AidRoutingManager;
+import com.android.nfc.cardemulation.CardEmulationManager;
+import com.android.nfc.cardemulation.Nfcid2RoutingManager;
+import com.android.nfc.cardemulation.Nfcid2RoutingCache;
+import com.android.nfc.cardemulation.RegisteredNfcid2Cache;
+import com.android.nfc.dhimpl.NativeNfcManager;
+import com.android.nfc.handover.HandoverDataParser;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.File;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import android.util.Pair;
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import com.nxp.nfc.INxpNfcAdapter;
+import com.nxp.intf.ILoaderService;
+import com.nxp.intf.IJcopService;
+import com.nxp.intf.INxpExtrasService;
+import com.nxp.intf.IeSEClientServicesAdapter;
+import com.nxp.nfc.INfcDta;
+import com.nxp.nfc.INfcVzw;
+import com.nxp.nfc.INxpNfcAdapterExtras;
+import com.nxp.nfc.INxpNfcAccessExtras;
+import com.nxp.nfc.NxpNfcAdapter;
+import com.nxp.nfc.NxpConstants;
+import com.vzw.nfc.RouteEntry;
+import com.gsma.nfc.internal.NxpNfcController;
+import com.nxp.nfc.gsma.internal.INxpNfcController;
+
+public class NfcService implements DeviceHostListener {
+ private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
+
+ static final boolean DBG = true;
+ static final String TAG = "NfcService";
+
+ public static final String SERVICE_NAME = "nfc";
+
+ /** Regular NFC permission */
+ private static final String NFC_PERM = android.Manifest.permission.NFC;
+ private static final String NFC_PERM_ERROR = "NFC permission required";
+
+ public static final String PREF = "NfcServicePrefs";
+
+ static final String PREF_NFC_ON = "nfc_on";
+ static final boolean NFC_ON_DEFAULT = true;
+ static final String PREF_NDEF_PUSH_ON = "ndef_push_on";
+ static final boolean NDEF_PUSH_ON_DEFAULT = true;
+ static final String PREF_FIRST_BEAM = "first_beam";
+ static final String PREF_FIRST_BOOT = "first_boot";
+ static final String PREF_AIRPLANE_OVERRIDE = "airplane_override";
+ private static final String PREF_SECURE_ELEMENT_ON = "secure_element_on";
+ private boolean SECURE_ELEMENT_ON_DEFAULT = false;
+ private int SECURE_ELEMENT_ID_DEFAULT = 0;
+ private static final String PREF_DEFAULT_ROUTE_ID = "default_route_id";
+ private static final String PREF_MIFARE_DESFIRE_PROTO_ROUTE_ID = "mifare_desfire_proto_route";
+ private static final String PREF_SET_DEFAULT_ROUTE_ID ="set_default_route";
+ private static final String PREF_MIFARE_CLT_ROUTE_ID= "mifare_clt_route";
+ private static final String LS_BACKUP_PATH = "/data/nfc/ls_backup.txt";
+ private static final String LS_UPDATE_BACKUP_PATH = "/data/nfc/loaderservice_updater.txt";
+ private static final String LS_UPDATE_BACKUP_OUT_PATH = "/data/nfc/loaderservice_updater_out.txt";
+
+ private static final String[] path = {"/data/nfc/JcopOs_Update1.apdu",
+ "/data/nfc/JcopOs_Update2.apdu",
+ "data/nfc/JcopOs_Update3.apdu"};
+
+ private static final String[] PREF_JCOP_MODTIME = {"jcop file1 modtime",
+ "jcop file2 modtime",
+ "jcop file3 modtime"};
+ private static final long[] JCOP_MODTIME_DEFAULT = {-1,-1,-1};
+ private static final long[] JCOP_MODTIME_TEMP = {-1,-1,-1};
+
+ private boolean ETSI_STOP_CONFIG = false;
+ private int ROUTE_ID_HOST= 0x00;
+ private int ROUTE_ID_SMX= 0x01;
+ private int ROUTE_ID_UICC= 0x02;
+
+ private int ROUTE_SWITCH_ON = 0x01;
+ private int ROUTE_SWITCH_OFF = 0x02;
+ private int ROUTE_BATT_OFF= 0x04;
+
+ private int TECH_TYPE_A= 0x01;
+ private int TECH_TYPE_B= 0x02;
+ private int TECH_TYPE_F= 0x04;
+
+ //TODO: Refer L_OSP_EXT [PN547C2]
+// private int DEFAULT_ROUTE_ID_DEFAULT = AidRoutingManager.DEFAULT_ROUTE;
+ private int DEFAULT_ROUTE_ID_DEFAULT = 0x00;
+ static final boolean SE_BROADCASTS_WITH_HCE = true;
+
+ private static final String PREF_SECURE_ELEMENT_ID = "secure_element_id";
+ public static final int ROUTE_LOC_MASK=3;
+ public static final int TECH_TYPE_MASK=5;
+
+ static final int MSG_NDEF_TAG = 0;
+ static final int MSG_CARD_EMULATION = 1;
+ static final int MSG_LLCP_LINK_ACTIVATION = 2;
+ static final int MSG_LLCP_LINK_DEACTIVATED = 3;
+ static final int MSG_TARGET_DESELECTED = 4;
+ static final int MSG_MOCK_NDEF = 7;
+ static final int MSG_SE_FIELD_ACTIVATED = 8;
+ static final int MSG_SE_FIELD_DEACTIVATED = 9;
+ static final int MSG_SE_APDU_RECEIVED = 10;
+ static final int MSG_SE_EMV_CARD_REMOVAL = 11;
+ static final int MSG_SE_MIFARE_ACCESS = 12;
+ static final int MSG_SE_LISTEN_ACTIVATED = 13;
+ static final int MSG_SE_LISTEN_DEACTIVATED = 14;
+ static final int MSG_LLCP_LINK_FIRST_PACKET = 15;
+ static final int MSG_ROUTE_AID = 16;
+ static final int MSG_UNROUTE_AID = 17;
+ static final int MSG_COMMIT_ROUTING = 18;
+ static final int MSG_INVOKE_BEAM = 19;
+
+ static final int MSG_SWP_READER_REQUESTED = 20;
+ static final int MSG_SWP_READER_ACTIVATED = 21;
+ static final int MSG_SWP_READER_DEACTIVATED = 22;
+ static final int MSG_CLEAR_ROUTING = 23;
+ static final int MSG_SET_SCREEN_STATE = 25;
+
+
+ static final int MSG_RF_FIELD_ACTIVATED = 26;
+ static final int MSG_RF_FIELD_DEACTIVATED = 27;
+ static final int MSG_RESUME_POLLING = 28;
+ static final int MSG_SWP_READER_REQUESTED_FAIL =29 ;
+ static final int MSG_SWP_READER_TAG_PRESENT = 30;
+ static final int MSG_SWP_READER_TAG_REMOVE = 31;
+ static final int MSG_CONNECTIVITY_EVENT = 40;
+ static final int MSG_VZW_ROUTE_AID = 41;
+ static final int MSG_VZW_COMMIT_ROUTING = 42;
+ static final int MSG_ROUTE_NFCID2 = 43;
+ static final int MSG_UNROUTE_NFCID2 = 44;
+ static final int MSG_COMMITINF_FELICA_ROUTING = 45;
+ static final int MSG_COMMITED_FELICA_ROUTING = 46;
+ static final int MSG_EMVCO_MULTI_CARD_DETECTED_EVENT = 47;
+ static final int MSG_ETSI_START_CONFIG = 48;
+ static final int MSG_ETSI_STOP_CONFIG = 49;
+ static final int MSG_ETSI_SWP_TIMEOUT = 50;
+ static final int MSG_APPLY_SREEN_STATE = 51;
+ static final long MAX_POLLING_PAUSE_TIMEOUT = 40000;
+ static final int TASK_ENABLE = 1;
+ static final int TASK_DISABLE = 2;
+ static final int TASK_BOOT = 3;
+ static final int TASK_EE_WIPE = 4;
+ static final int MSG_CHANGE_DEFAULT_ROUTE = 52;
+ static final int MSG_SE_DELIVER_INTENT = 53;
+
+ // Copied from com.android.nfc_extras to avoid library dependency
+ // Must keep in sync with com.android.nfc_extras
+ static final int ROUTE_OFF = 1;
+ static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
+
+ // Return values from NfcEe.open() - these are 1:1 mapped
+ // to the thrown EE_EXCEPTION_ exceptions in nfc-extras.
+ static final int EE_ERROR_IO = -1;
+ static final int EE_ERROR_ALREADY_OPEN = -2;
+ static final int EE_ERROR_INIT = -3;
+ static final int EE_ERROR_LISTEN_MODE = -4;
+ static final int EE_ERROR_EXT_FIELD = -5;
+ static final int EE_ERROR_NFC_DISABLED = -6;
+
+ // Polling technology masks
+ static final int NFC_POLL_A = 0x01;
+ static final int NFC_POLL_B = 0x02;
+ static final int NFC_POLL_F = 0x04;
+ static final int NFC_POLL_ISO15693 = 0x08;
+ static final int NFC_POLL_B_PRIME = 0x10;
+ static final int NFC_POLL_KOVIO = 0x20;
+
+ // minimum screen state that enables NFC polling
+ static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
+
+ // Time to wait for NFC controller to initialize before watchdog
+ // goes off. This time is chosen large, because firmware download
+ // may be a part of initialization.
+ static final int INIT_WATCHDOG_MS = 90000;
+ static final int INIT_WATCHDOG_LS_MS = 180000;
+ // Time to wait for routing to be applied before watchdog
+ // goes off
+ static final int ROUTING_WATCHDOG_MS = 10000;
+
+ // Amount of time to wait before closing the NFCEE connection
+ // in a disable/shutdown scenario.
+ static final int WAIT_FOR_NFCEE_OPERATIONS_MS = 5000;
+ // Polling interval for waiting on NFCEE operations
+ static final int WAIT_FOR_NFCEE_POLL_MS = 100;
+
+ // Default delay used for presence checks
+ static final int DEFAULT_PRESENCE_CHECK_DELAY = 125;
+
+ //Delay used for presence checks of NFC_F non-Ndef
+ //Make secure communication done or tranceive next request response command
+ //to pause timer before presence check command is sent
+ static final int NFC_F_TRANSCEIVE_PRESENCE_CHECK_DELAY = 500;
+
+ // The amount of time we wait before manually launching
+ // the Beam animation when called through the share menu.
+ static final int INVOKE_BEAM_DELAY_MS = 1000;
+ // for use with playSound()
+ public static final int SOUND_START = 0;
+ public static final int SOUND_END = 1;
+ public static final int SOUND_ERROR = 2;
+
+ // for setting VEN_CFG
+ public static final int VEN_CFG_NFC_ON_POWER_ON = 3;
+ public static final int VEN_CFG_NFC_OFF_POWER_OFF = 2;
+
+ //ETSI Reader Events
+ public static final int ETSI_READER_REQUESTED = 0;
+ public static final int ETSI_READER_START = 1;
+ public static final int ETSI_READER_STOP = 2;
+
+ //ETSI Reader Req States
+ public static final int STATE_SE_RDR_MODE_INVALID = 0x00;
+ public static final int STATE_SE_RDR_MODE_START_CONFIG = 0x01;
+ public static final int STATE_SE_RDR_MODE_START_IN_PROGRESS = 0x02;
+ public static final int STATE_SE_RDR_MODE_STARTED = 0x03;
+ public static final int STATE_SE_RDR_MODE_ACTIVATED = 0x04;
+ public static final int STATE_SE_RDR_MODE_STOP_CONFIG = 0x05;
+ public static final int STATE_SE_RDR_MODE_STOP_IN_PROGRESS = 0x06;
+ public static final int STATE_SE_RDR_MODE_STOPPED = 0x07;
+
+ public static final String ACTION_RF_FIELD_ON_DETECTED =
+ "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
+ public static final String ACTION_RF_FIELD_OFF_DETECTED =
+ "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
+ public static final String ACTION_AID_SELECTED =
+ "com.android.nfc_extras.action.AID_SELECTED";
+ public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
+
+ public static final String ACTION_LLCP_UP =
+ "com.android.nfc.action.LLCP_UP";
+
+ public static final String ACTION_LLCP_DOWN =
+ "com.android.nfc.action.LLCP_DOWN";
+
+ public static final String ACTION_APDU_RECEIVED =
+ "com.android.nfc_extras.action.APDU_RECEIVED";
+ public static final String EXTRA_APDU_BYTES =
+ "com.android.nfc_extras.extra.APDU_BYTES";
+
+ public static final String ACTION_EMV_CARD_REMOVAL =
+ "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
+
+ public static final String ACTION_MIFARE_ACCESS_DETECTED =
+ "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
+ public static final String EXTRA_MIFARE_BLOCK =
+ "com.android.nfc_extras.extra.MIFARE_BLOCK";
+
+ public static final String ACTION_SE_LISTEN_ACTIVATED =
+ "com.android.nfc_extras.action.SE_LISTEN_ACTIVATED";
+ public static final String ACTION_SE_LISTEN_DEACTIVATED =
+ "com.android.nfc_extras.action.SE_LISTEN_DEACTIVATED";
+
+ public static final String ACTION_EMVCO_MULTIPLE_CARD_DETECTED =
+ "com.nxp.action.EMVCO_MULTIPLE_CARD_DETECTED";
+
+ private static final String PACKAGE_SMART_CARD_SERVICE = "org.simalliance.openmobileapi.service";
+ /**
+ * SMART MX ID to be able to select it as the default Secure Element
+ */
+ public static final int SMART_MX_ID_TYPE = 1;
+
+ /**
+ * UICC ID to be able to select it as the default Secure Element
+ */
+ public static final int UICC_ID_TYPE = 2;
+
+ /**
+ * ID to be able to select all Secure Elements
+ */
+ public static final int ALL_SE_ID_TYPE = 3;
+
+ public static final int PN547C2_ID = 1;
+ public static final int PN65T_ID = 2;
+ public static final int PN548AD_ID = 3;
+ public static final int PN66T_ID = 4;
+
+ public static final int LS_RETRY_CNT = 3;
+ public static final int LOADER_SERVICE_VERSION_21 = 0x21;
+ private int mSelectedSeId = 0;
+ private boolean mNfcSecureElementState;
+ private boolean mIsSmartCardServiceSupported = false;
+ // Timeout to re-apply routing if a tag was present and we postponed it
+ private static final int APPLY_ROUTING_RETRY_TIMEOUT_MS = 5000;
+
+ private final UserManager mUserManager;
+ // NFC Execution Environment
+ // fields below are protected by this
+ private NativeNfcSecureElement mSecureElement;
+ private OpenSecureElement mOpenEe; // null when EE closed
+ private final ReaderModeDeathRecipient mReaderModeDeathRecipient =
+ new ReaderModeDeathRecipient();
+ private final NfcUnlockManager mNfcUnlockManager;
+
+ private int mEeRoutingState; // contactless interface routing
+ private int mLockscreenPollMask;
+ List<PackageInfo> mInstalledPackages; // cached version of installed packages
+ private NativeNfcAla mNfcAla;
+
+ NfcAccessExtrasService mNfcAccessExtrasService;
+
+ // fields below are used in multiple threads and protected by synchronized(this)
+ final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
+ // mSePackages holds packages that accessed the SE, but only for the owner user,
+ // as SE access is not granted for non-owner users.
+ HashSet<String> mSePackages = new HashSet<String>();
+ int mScreenState;
+ boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning
+ boolean mIsNdefPushEnabled;
+ boolean mNfcPollingEnabled; // current Device Host state of NFC-C polling
+ boolean mHostRouteEnabled; // current Device Host state of host-based routing
+ boolean mReaderModeEnabled; // current Device Host state of reader mode
+ boolean mNfceeRouteEnabled; // current Device Host state of NFC-EE routing
+ NfcDiscoveryParameters mCurrentDiscoveryParameters =
+ NfcDiscoveryParameters.getNfcOffParameters();
+ ReaderModeParams mReaderModeParams;
+
+ // mState is protected by this, however it is only modified in onCreate()
+ // and the default AsyncTask thread so it is read unprotected from that
+ // thread
+ int mState; // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc
+ boolean mPowerShutDown = false; // State for power shut down state
+
+ // fields below are final after onCreate()
+ Context mContext;
+ private DeviceHost mDeviceHost;
+ private SharedPreferences mPrefs;
+ private SharedPreferences.Editor mPrefsEditor;
+ private PowerManager.WakeLock mRoutingWakeLock;
+ private PowerManager.WakeLock mEeWakeLock;
+
+ int mStartSound;
+ int mEndSound;
+ int mErrorSound;
+ SoundPool mSoundPool; // playback synchronized on this
+ P2pLinkManager mP2pLinkManager;
+ TagService mNfcTagService;
+ NfcAdapterService mNfcAdapter;
+ NfcAdapterExtrasService mExtrasService;
+// CardEmulationService mCardEmulationService;
+ NxpNfcAdapterService mNxpNfcAdapter;
+ NxpNfcAdapterExtrasService mNxpExtrasService;
+ NxpExtrasService mNxpExtras;
+ EseClientServicesAdapter mEseClientServicesAdapter;
+ boolean mIsAirplaneSensitive;
+ boolean mIsAirplaneToggleable;
+ boolean mIsDebugBuild;
+ boolean mIsHceCapable;
+ boolean mPollingPaused;
+ boolean mIsRoutingTableDirty;
+ boolean mIsFelicaOnHostConfigured;
+ boolean mIsFelicaOnHostConfiguring;
+
+ public boolean mIsRouteForced;
+ NfceeAccessControl mNfceeAccessControl;
+ NfcSccAccessControl mNfcSccAccessControl;
+ NfcSeAccessControl mNfcSeAccessControl;
+ NfcAlaService mAlaService;
+ NfcJcopService mJcopService;
+ NfcDtaService mDtaService;
+ NfcVzwService mVzwService;
+ private NfcDispatcher mNfcDispatcher;
+ private PowerManager mPowerManager;
+ private KeyguardManager mKeyguard;
+ ToastHandler mToastHandler;
+ private HandoverDataParser mHandoverDataParser;
+ private ContentResolver mContentResolver;
+ // private RegisteredAidCache mAidCache;
+ private CardEmulationManager mCardEmulationManager;
+ private AidRoutingManager mAidRoutingManager;
+ private Nfcid2RoutingManager mNfcid2RoutingManager;
+ private ScreenStateHelper mScreenStateHelper;
+ private ForegroundUtils mForegroundUtils;
+ private boolean mClearNextTapDefault;
+ private NxpNfcController mNxpNfcController;
+
+ private int mUserId;
+ private static NfcService sService;
+ public static boolean mIsDtaMode = false;
+ public static boolean mIsShortRecordLayout = false;
+ public static boolean fAidTableFull = false;
+
+ //GSMA
+ private final Boolean defaultTransactionEventReceptionMode = Boolean.FALSE;
+ private final static Boolean multiReceptionMode = Boolean.TRUE;
+ private final static Boolean unicastReceptionMode = Boolean.FALSE;
+ boolean mIsSentUnicastReception = false;
+
+ public void enforceNfcSeAdminPerm(String pkg) {
+ if (pkg == null) {
+ throw new SecurityException("caller must pass a package name");
+ }
+ mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
+ if (!mNfcSeAccessControl.check(Binder.getCallingUid(), pkg)) {
+ throw new SecurityException(NfcSeAccessControl.NFCSE_ACCESS_PATH +
+ " denies NFCSe access to " + pkg);
+ }
+ if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ throw new SecurityException("only the owner is allowed to act as SCC admin");
+ }
+ }
+ public void enforceNfceeAdminPerm(String pkg) {
+ if (pkg == null) {
+ throw new SecurityException("caller must pass a package name");
+ }
+ NfcPermissions.enforceUserPermissions(mContext);
+ if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) {
+ throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH +
+ " denies NFCEE access to " + pkg);
+ }
+ if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ throw new SecurityException("only the owner is allowed to call SE APIs");
+ }
+ }
+
+
+ /* SCC Access Control */
+ public void enforceNfcSccAdminPerm(String pkg) {
+ if (pkg == null) {
+ throw new SecurityException("caller must pass a package name");
+ }
+ mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
+ if (!mNfcSccAccessControl.check(Binder.getCallingUid(), pkg)) {
+ throw new SecurityException(NfcSccAccessControl.NFCSCC_ACCESS_PATH +
+ " denies NFCSCC access to " + pkg);
+ }
+ if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ throw new SecurityException("only the owner is allowed to act as SCC admin");
+ }
+ }
+
+ public static NfcService getInstance() {
+ return sService;
+ }
+
+ @Override
+ public void onRemoteEndpointDiscovered(TagEndpoint tag) {
+ sendMessage(NfcService.MSG_NDEF_TAG, tag);
+ }
+
+ public int getRemainingAidTableSize() {
+ return mDeviceHost.getRemainingAidTableSize();
+ }
+
+ public int getChipVer() {
+ return mDeviceHost.getChipVer();
+ }
+ /**
+ * Notifies Card emulation deselect
+ */
+ @Override
+ public void onCardEmulationDeselected() {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ sendMessage(NfcService.MSG_TARGET_DESELECTED, null);
+ }
+ }
+
+ /**
+ * Notifies transaction
+ */
+ @Override
+ public void onCardEmulationAidSelected(byte[] aid, byte[] data, int evtSrc) {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ Pair<byte[], Integer> dataSrc = new Pair<byte[], Integer>(data, evtSrc);
+ Pair<byte[], Pair> transactionInfo = new Pair<byte[], Pair>(aid, dataSrc);
+ Log.d(TAG, "onCardEmulationAidSelected : Source" + evtSrc);
+
+ sendMessage(NfcService.MSG_CARD_EMULATION, transactionInfo);
+ }
+ }
+
+ /**
+ * Notifies connectivity
+ */
+ @Override
+ public void onConnectivityEvent(int evtSrc) {
+ Log.d(TAG, "onConnectivityEvent : Source" + evtSrc);
+ sendMessage(NfcService.MSG_CONNECTIVITY_EVENT, evtSrc);
+ }
+
+ @Override
+ public void onEmvcoMultiCardDetectedEvent() {
+ Log.d(TAG, "onEmvcoMultiCardDetectedEvent");
+ sendMessage(NfcService.MSG_EMVCO_MULTI_CARD_DETECTED_EVENT,null);
+ }
+
+ /**
+ * Notifies transaction
+ */
+ @Override
+ public void onHostCardEmulationActivated() {
+ if (mCardEmulationManager != null) {
+ mCardEmulationManager.onHostCardEmulationActivated();
+ }
+ }
+
+ @Override
+ public void onAidRoutingTableFull() {
+ Log.d(TAG, "NxpNci: onAidRoutingTableFull: AID Routing Table is FULL!");
+ /*if((ROUTE_ID_HOST != GetDefaultRouteLoc())&&(fAidTableFull == false))
+ {
+ Log.d(TAG, "NxpNci: onAidRoutingTableFull: Making Default Route to HOST!");
+ fAidTableFull = true;
+ mHandler.sendEmptyMessage(NfcService.MSG_CHANGE_DEFAULT_ROUTE);
+ }*/
+ if (mIsHceCapable) {
+ mAidRoutingManager.onNfccRoutingTableCleared();
+ mCardEmulationManager.onRoutingTableChanged();
+ }
+ }
+
+ @Override
+ public void onHostCardEmulationData(byte[] data) {
+ if (mCardEmulationManager != null) {
+ mCardEmulationManager.onHostCardEmulationData(data);
+ }
+ }
+
+ @Override
+ public void onHostCardEmulationDeactivated() {
+ if (mCardEmulationManager != null) {
+ mCardEmulationManager.onHostCardEmulationDeactivated();
+ }
+ }
+
+ /**
+ * Notifies P2P Device detected, to activate LLCP link
+ */
+ @Override
+ public void onLlcpLinkActivated(NfcDepEndpoint device) {
+ sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
+ }
+
+ /**
+ * Notifies P2P Device detected, to activate LLCP link
+ */
+ @Override
+ public void onLlcpLinkDeactivated(NfcDepEndpoint device) {
+ sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device);
+ }
+
+ /**
+ * Notifies P2P Device detected, first packet received over LLCP link
+ */
+ @Override
+ public void onLlcpFirstPacketReceived(NfcDepEndpoint device) {
+ sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device);
+ }
+
+ @Override
+ public void onRemoteFieldActivated() {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null);
+ }
+ }
+
+ @Override
+ public void onRemoteFieldDeactivated() {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null);
+ }
+ }
+
+ @Override
+ public void onSeListenActivated() {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ sendMessage(NfcService.MSG_SE_LISTEN_ACTIVATED, null);
+ }
+ if (mIsHceCapable) {
+ mCardEmulationManager.onHostCardEmulationActivated();
+ }
+ }
+
+ @Override
+ public void onSeListenDeactivated() {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ sendMessage(NfcService.MSG_SE_LISTEN_DEACTIVATED, null);
+ }
+ if( mIsHceCapable) {
+ mCardEmulationManager.onHostCardEmulationDeactivated();
+ }
+ }
+
+
+ @Override
+ public void onSeApduReceived(byte[] apdu) {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu);
+ }
+ }
+
+ @Override
+ public void onSeEmvCardRemoval() {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null);
+ }
+ }
+
+ @Override
+ public void onSeMifareAccess(byte[] block) {
+ if (!mIsHceCapable || SE_BROADCASTS_WITH_HCE) {
+ sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block);
+ }
+ }
+
+ @Override
+ public void onSWPReaderRequestedEvent(boolean istechA, boolean istechB)
+ {
+ int size=0;
+ ArrayList<Integer> techList = new ArrayList<Integer>();
+ if(istechA)
+ techList.add(TagTechnology.NFC_A);
+ if(istechB)
+ techList.add(TagTechnology.NFC_B);
+
+ sendMessage(NfcService.MSG_SWP_READER_REQUESTED , techList);
+ }
+
+ @Override
+ public void onSWPReaderRequestedFail(int FailCause)
+ {
+ sendMessage(NfcService.MSG_SWP_READER_REQUESTED_FAIL , FailCause);
+ }
+
+ @Override
+ public void onSWPReaderActivatedEvent()
+ {
+ sendMessage(NfcService.MSG_SWP_READER_ACTIVATED, null);
+ }
+
+ @Override
+ public void onETSIReaderModeStartConfig(int eeHandle)
+ {
+ ArrayList<Integer> configList = new ArrayList<Integer>();
+ configList.add(eeHandle);
+ sendMessage(NfcService.MSG_ETSI_START_CONFIG, configList);
+ }
+
+ @Override
+ public void onETSIReaderModeStopConfig(int disc_ntf_timeout)
+ {
+ sendMessage(NfcService.MSG_ETSI_STOP_CONFIG, disc_ntf_timeout);
+ }
+
+ @Override
+ public void onETSIReaderModeSwpTimeout(int disc_ntf_timeout)
+ {
+ sendMessage(NfcService.MSG_ETSI_SWP_TIMEOUT, disc_ntf_timeout);
+ }
+
+ final class ReaderModeParams {
+ public int flags;
+ public IAppCallback callback;
+ public int presenceCheckDelay;
+ }
+
+ public NfcService(Application nfcApplication) {
+ mUserId = ActivityManager.getCurrentUser();
+ mContext = nfcApplication;
+
+ mNfcTagService = new TagService();
+ mNfcAdapter = new NfcAdapterService();
+ mNxpNfcAdapter = new NxpNfcAdapterService();
+ mExtrasService = new NfcAdapterExtrasService();
+ mNxpExtrasService = new NxpNfcAdapterExtrasService();
+ // mCardEmulationService = new CardEmulationService();
+
+ Log.i(TAG, "Starting NFC service");
+
+ sService = this;
+
+ mScreenStateHelper = new ScreenStateHelper(mContext);
+ mContentResolver = mContext.getContentResolver();
+ mDeviceHost = new NativeNfcManager(mContext, this);
+
+ mNfcUnlockManager = NfcUnlockManager.getInstance();
+
+ mHandoverDataParser = new HandoverDataParser();
+ boolean isNfcProvisioningEnabled = false;
+ try {
+ isNfcProvisioningEnabled = mContext.getResources().getBoolean(
+ R.bool.enable_nfc_provisioning);
+ } catch (NotFoundException e) {
+ }
+
+ if (isNfcProvisioningEnabled) {
+ mInProvisionMode = Settings.Secure.getInt(mContentResolver,
+ Settings.Global.DEVICE_PROVISIONED, 0) == 0;
+ } else {
+ mInProvisionMode = false;
+ }
+
+ mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode);
+ mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser,
+ mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
+
+ mSecureElement = new NativeNfcSecureElement(mContext);
+ mEeRoutingState = ROUTE_OFF;
+ mToastHandler = new ToastHandler(mContext);
+
+ mNfceeAccessControl = new NfceeAccessControl(mContext);
+ mNfcSccAccessControl = new NfcSccAccessControl(mContext);
+ mNfcSeAccessControl = new NfcSeAccessControl(mContext);
+ mNfcAla = new NativeNfcAla();
+
+ mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
+ mPrefsEditor = mPrefs.edit();
+
+ mState = NfcAdapter.STATE_OFF;
+ mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
+ setBeamShareActivityState(mIsNdefPushEnabled);
+
+ mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE);
+
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
+ mRoutingWakeLock = mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
+ mEeWakeLock = mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock");
+
+ mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+ mScreenState = mScreenStateHelper.checkScreenState();
+
+ ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
+
+ // Intents for all users
+ IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_USER_PRESENT);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_SHUTDOWN);
+ registerForAirplaneMode(filter);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
+
+ IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+ mContext.registerReceiver(mOwnerReceiver, ownerFilter);
+
+ ownerFilter = new IntentFilter();
+ ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ ownerFilter.addDataScheme("package");
+ mContext.registerReceiver(mOwnerReceiver, ownerFilter);
+
+ IntentFilter x509CertificateFilter = new IntentFilter();
+ x509CertificateFilter.addAction(NxpConstants.ACTION_CHECK_X509_RESULT);
+ mContext.registerReceiver(x509CertificateReceiver, x509CertificateFilter);
+
+ IntentFilter enableNfc = new IntentFilter();
+ enableNfc.addAction(NxpConstants.ACTION_GSMA_ENABLE_NFC);
+ mContext.registerReceiver(mEnableNfc, enableNfc);
+
+ IntentFilter lsFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+ //mContext.registerReceiver(mAlaReceiver, lsFilter);
+ mContext.registerReceiverAsUser(mAlaReceiver, UserHandle.ALL, lsFilter, null, null);
+
+ IntentFilter policyFilter = new IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+ mContext.registerReceiverAsUser(mPolicyReceiver, UserHandle.ALL, policyFilter, null, null);
+
+ updatePackageCache();
+
+ PackageManager pm = mContext.getPackageManager();
+ mIsHceCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
+ if (mIsHceCapable) {
+ mAidRoutingManager = new AidRoutingManager();
+ mNfcid2RoutingManager = new Nfcid2RoutingManager();
+ mCardEmulationManager = new CardEmulationManager(mContext, mAidRoutingManager, mNfcid2RoutingManager);
+ //mCardEmulationManager = new CardEmulationManager(mContext);
+ Log.d("NfcService", "Before mIsHceCapable");
+ mNxpNfcController = new NxpNfcController(mContext, mCardEmulationManager);
+ }
+
+ mForegroundUtils = ForegroundUtils.getInstance();
+ new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks
+ }
+
+ void initSoundPool() {
+ synchronized(this) {
+ if (mSoundPool == null) {
+ mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
+ mStartSound = mSoundPool.load(mContext, R.raw.start, 1);
+ mEndSound = mSoundPool.load(mContext, R.raw.end, 1);
+ mErrorSound = mSoundPool.load(mContext, R.raw.error, 1);
+ }
+ }
+ }
+
+ void releaseSoundPool() {
+ synchronized (this) {
+ if (mSoundPool != null) {
+ mSoundPool.release();
+ mSoundPool = null;
+ }
+ }
+ }
+
+ void registerForAirplaneMode(IntentFilter filter) {
+ final String airplaneModeRadios = Settings.System.getString(mContentResolver,
+ Settings.Global.AIRPLANE_MODE_RADIOS);
+ final String toggleableRadios = Settings.System.getString(mContentResolver,
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+
+ mIsAirplaneSensitive = airplaneModeRadios == null ? true :
+ airplaneModeRadios.contains(Settings.Global.RADIO_NFC);
+ mIsAirplaneToggleable = toggleableRadios == null ? false :
+ toggleableRadios.contains(Settings.Global.RADIO_NFC);
+
+ if (mIsAirplaneSensitive) {
+ filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ }
+ }
+ void updatePackageCache() {
+ PackageManager pm = mContext.getPackageManager();
+ List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER);
+ synchronized (this) {
+ mInstalledPackages = packages;
+ }
+ }
+
+ int doOpenSecureElementConnection() {
+ mEeWakeLock.acquire();
+ try {
+ return mSecureElement.doOpenSecureElementConnection();
+ } finally {
+ mEeWakeLock.release();
+ }
+ }
+
+ byte[] doTransceive(int handle, byte[] cmd) {
+ mEeWakeLock.acquire();
+ try {
+ return doTransceiveNoLock(handle, cmd);
+ } finally {
+ mEeWakeLock.release();
+ }
+ }
+
+ byte[] doTransceiveNoLock(int handle, byte[] cmd) {
+ return mSecureElement.doTransceive(handle, cmd);
+ }
+
+ void doDisconnect(int handle) {
+ mEeWakeLock.acquire();
+ try {
+ mSecureElement.doDisconnect(handle);
+ } finally {
+ mEeWakeLock.release();
+ }
+ }
+
+ boolean doReset(int handle) {
+ mEeWakeLock.acquire();
+ try {
+ return mSecureElement.doReset(handle);
+ } finally {
+ mEeWakeLock.release();
+ }
+ }
+
+ public static byte[] CreateSHA(String pkg, int alaVer){
+ String TAG = "Utils:CreateSHA";
+ StringBuffer sb = new StringBuffer();
+ try {
+ MessageDigest md;
+ if(alaVer == 1)
+ md = MessageDigest.getInstance("SHA-256");
+ else
+ md = MessageDigest.getInstance("SHA-1");
+
+ md.update(pkg.getBytes());
+
+ byte byteData[] = md.digest();
+ Log.i(TAG, "byteData len : " + byteData.length);
+ /*
+ for (int i = 0; i < byteData.length; i++) {
+ sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
+ }
+ // Log.i(TAG, "sb.toString()" + sb.toString());*/
+ return byteData;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static String getCallingAppPkg(Context context) {
+ String TAG = "getCallingAppPkg";
+ ActivityManager am = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
+
+ // get the info from the currently running task
+ List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);
+
+ Log.d("topActivity", "CURRENT Activity ::"
+ + taskInfo.get(0).topActivity.getClassName());
+ String s = taskInfo.get(0).topActivity.getClassName();
+
+ ComponentName componentInfo = taskInfo.get(0).topActivity;
+ componentInfo.getPackageName();
+ Log.i(TAG,"componentInfo.getPackageName()" + componentInfo.getPackageName());
+ return componentInfo.getPackageName();
+ }
+
+ /**
+ * Manages tasks that involve turning on/off the NFC controller.
+ * <p/>
+ * <p>All work that might turn the NFC adapter on or off must be done
+ * through this task, to keep the handling of mState simple.
+ * In other words, mState is only modified in these tasks (and we
+ * don't need a lock to read it in these tasks).
+ * <p/>
+ * <p>These tasks are all done on the same AsyncTask background
+ * thread, so they are serialized. Each task may temporarily transition
+ * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in
+ * either STATE_ON or STATE_OFF. This way each task can be guaranteed
+ * of starting in either STATE_OFF or STATE_ON, without needing to hold
+ * NfcService.this for the entire task.
+ * <p/>
+ * <p>AsyncTask's are also implicitly queued. This is useful for corner
+ * cases like turning airplane mode on while TASK_ENABLE is in progress.
+ * The TASK_DISABLE triggered by airplane mode will be correctly executed
+ * immediately after TASK_ENABLE is complete. This seems like the most sane
+ * way to deal with these situations.
+ * <p/>
+ * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing
+ * preferences
+ * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing
+ * preferences
+ * <p>{@link #TASK_BOOT} does first boot work and may enable NFC
+ */
+ class EnableDisableTask extends AsyncTask<Integer, Void, Void> {
+ @Override
+ protected Void doInBackground(Integer... params) {
+ // Sanity check mState
+ switch (mState) {
+ case NfcAdapter.STATE_TURNING_OFF:
+ case NfcAdapter.STATE_TURNING_ON:
+ Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " +
+ mState);
+ return null;
+ }
+
+ /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND,
+ * override with the default. THREAD_PRIORITY_BACKGROUND causes
+ * us to service software I2C too slow for firmware download
+ * with the NXP PN544.
+ * TODO: move this to the DAL I2C layer in libnfc-nxp, since this
+ * problem only occurs on I2C platforms using PN544
+ */
+ Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+
+ switch (params[0].intValue()) {
+ case TASK_ENABLE:
+ enableInternal();
+ break;
+ case TASK_DISABLE:
+ disableInternal();
+ break;
+ case TASK_BOOT:
+ Log.d(TAG, "checking on firmware download");
+ boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false);
+ if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) &&
+ (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) {
+ Log.d(TAG, "NFC is on. Doing normal stuff");
+ enableInternal();
+ } else {
+ Log.d(TAG, "NFC is off. Checking firmware version");
+ mDeviceHost.checkFirmware();
+ }
+ if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
+ Log.i(TAG, "First Boot");
+ mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
+ mPrefsEditor.apply();
+ }
+ break;
+ }
+
+ // Restore default AsyncTask priority
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+
+ if(mState == NfcAdapter.STATE_ON){
+ IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_USER_PRESENT);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_SHUTDOWN);
+ registerForAirplaneMode(filter);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
+ }else if (mState == NfcAdapter.STATE_OFF){
+ mContext.unregisterReceiver(mReceiver);
+ IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_SHUTDOWN);
+ registerForAirplaneMode(filter);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
+ }
+
+
+ }
+
+ /**
+ * Check the default Secure Element configuration.
+ */
+ void checkSecureElementConfuration() {
+
+ /* Get SE List */
+ int[] Se_list = mDeviceHost.doGetSecureElementList();
+
+ /* Check Secure Element setting */
+ int Se_Num=mDeviceHost.GetDefaultSE();
+ if(Se_Num != 0)
+ {
+ SECURE_ELEMENT_ON_DEFAULT=true;
+ SECURE_ELEMENT_ID_DEFAULT=Se_Num;
+ } else {
+ if (Se_list != null) {
+ for (int i = 0; i < Se_list.length; i++) {
+ mDeviceHost.doDeselectSecureElement(Se_list[i]);
+ }
+ }
+ }
+
+ mNfcSecureElementState =
+ mPrefs.getBoolean(PREF_SECURE_ELEMENT_ON, SECURE_ELEMENT_ON_DEFAULT);
+
+ if (mNfcSecureElementState) {
+ int secureElementId =
+ mPrefs.getInt(PREF_SECURE_ELEMENT_ID, SECURE_ELEMENT_ID_DEFAULT);
+
+ if (Se_list != null) {
+
+ if (secureElementId != ALL_SE_ID_TYPE/* SECURE_ELEMENT_ALL */) {
+ mDeviceHost.doDeselectSecureElement(UICC_ID_TYPE);
+ mDeviceHost.doDeselectSecureElement(SMART_MX_ID_TYPE);
+
+ for (int i = 0; i < Se_list.length; i++) {
+
+ if (Se_list[i] == secureElementId) {
+ if (secureElementId == SMART_MX_ID_TYPE) { // SECURE_ELEMENT_SMX_ID
+ if (Se_list.length > 1) {
+ if (DBG) {
+ Log.d(TAG, "Deselect UICC");
+ }
+ }
+ Log.d(TAG, "Select SMX");
+ mDeviceHost.doSelectSecureElement(secureElementId);
+ mSelectedSeId = secureElementId;
+ break;
+ } else if (secureElementId == UICC_ID_TYPE/* SECURE_ELEMENT_UICC_ID */) {
+ if (Se_list.length > 1) {
+ if (DBG) {
+ Log.d(TAG, "Deselect SMX");
+ }
+ }
+ Log.d(TAG, "Select UICC");
+ mDeviceHost.doSelectSecureElement(secureElementId);
+ mSelectedSeId = secureElementId;
+ break;
+ } else if (secureElementId == SECURE_ELEMENT_ID_DEFAULT) {
+ if (Se_list.length > 1) {
+ if (DBG) {
+ Log.d(TAG, "UICC deselected by default");
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if (DBG) {
+ Log.d(TAG, "Select ALL_SE");
+ }
+
+ if (Se_list.length > 1) {
+
+ for (int i = 0; i < Se_list.length; i++) {
+ mDeviceHost.doSelectSecureElement(Se_list[i]);
+ try{
+ //Delay b/w two SE selection.
+ Thread.sleep(200);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ mSelectedSeId = secureElementId;
+ }
+ }
+ }
+ } else {
+ if (Se_list != null && Se_list.length > 0) {
+ if (DBG) {
+ Log.d(TAG, "UICC/eSE deselected by default");
+ }
+ mDeviceHost.doDeselectSecureElement(UICC_ID_TYPE);
+ mDeviceHost.doDeselectSecureElement(SMART_MX_ID_TYPE);
+ }
+ }
+ }
+
+ boolean getJcopOsFileInfo() {
+ File jcopOsFile;
+ Log.i(TAG, "getJcopOsFileInfo");
+
+ for (int num = 0; num < 3; num++) {
+ try{
+ jcopOsFile = new File(path[num]);
+ }catch(NullPointerException npe) {
+ Log.e(TAG,"path to jcop os file was null");
+ return false;
+ }
+ long modtime = jcopOsFile.lastModified();
+ SharedPreferences prefs = mContext.getSharedPreferences(PREF,Context.MODE_PRIVATE);
+ long prev_modtime = prefs.getLong(PREF_JCOP_MODTIME[num], JCOP_MODTIME_DEFAULT[num]);
+ Log.d(TAG,"prev_modtime:" + prev_modtime);
+ Log.d(TAG,"new_modtime:" + modtime);
+ if(prev_modtime == modtime){
+ return false;
+ }
+ JCOP_MODTIME_TEMP[num] = modtime;
+ }
+ return true;
+ }
+
+ /* jcop os Download at boot time */
+ void jcopOsDownload() {
+ int status = ErrorCodes.SUCCESS;
+ boolean jcopStatus;
+ Log.i(TAG, "Jcop Download starts");
+
+ SharedPreferences prefs = mContext.getSharedPreferences(PREF,Context.MODE_PRIVATE);
+ jcopStatus = getJcopOsFileInfo();
+
+ if( jcopStatus == true) {
+ Log.i(TAG, "Starting getChipName");
+ int Ver = mDeviceHost.getChipVer();
+ if(Ver == PN66T_ID || Ver == PN65T_ID) {
+ status = mDeviceHost.JCOSDownload();
+ }
+ if(status != ErrorCodes.SUCCESS) {
+ Log.i(TAG, "Jcop Download failed");
+ }
+ else {
+ Log.i(TAG, "Jcop Download success");
+ prefs.edit().putLong(PREF_JCOP_MODTIME[0],JCOP_MODTIME_TEMP[0]).apply();
+ prefs.edit().putLong(PREF_JCOP_MODTIME[1],JCOP_MODTIME_TEMP[1]).apply();
+ prefs.edit().putLong(PREF_JCOP_MODTIME[2],JCOP_MODTIME_TEMP[2]).apply();
+ }
+ }
+ }
+ /**
+ * Enable NFC adapter functions.
+ * Does not toggle preferences.
+ */
+ boolean enableInternal() {
+ if (mState == NfcAdapter.STATE_ON) {
+ return true;
+ }
+ Log.i(TAG, "Enabling NFC");
+ updateState(NfcAdapter.STATE_TURNING_ON);
+ int timeout = mDeviceHost.getNfcInitTimeout();
+ if (timeout < INIT_WATCHDOG_MS)
+ {
+ timeout = INIT_WATCHDOG_MS;
+ }
+ Log.i(TAG, "Enabling NFC timeout" +timeout);
+ WatchDogThread watchDog = new WatchDogThread("enableInternal", timeout);
+ watchDog.start();
+ try {
+ mRoutingWakeLock.acquire();
+ try {
+ if (!mDeviceHost.initialize()) {
+ Log.w(TAG, "Error enabling NFC");
+ updateState(NfcAdapter.STATE_OFF);
+ return false;
+ }
+ } finally {
+ mRoutingWakeLock.release();
+ }
+ } finally {
+ watchDog.cancel();
+ }
+ checkSecureElementConfuration();
+
+ mIsRouteForced = true;
+ if (mIsHceCapable) {
+ // Generate the initial card emulation routing table
+ fAidTableFull = false;
+ mCardEmulationManager.onNfcEnabled();
+ }
+ mIsRouteForced = false;
+
+ synchronized (NfcService.this) {
+ mObjectMap.clear();
+ mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
+ updateState(NfcAdapter.STATE_ON);
+ }
+
+ synchronized (NfcService.this) {
+ if(mDeviceHost.doCheckJcopDlAtBoot()) {
+ /* start jcop download */
+ Log.i(TAG, "Calling Jcop Download");
+ jcopOsDownload();
+ }
+ }
+
+ initSoundPool();
+ /* Start polling loop */
+ Log.e(TAG, "applyRouting -3");
+ mScreenState = mScreenStateHelper.checkScreenState();
+ mDeviceHost.doSetScreenOrPowerState(mScreenState);
+ mIsRoutingTableDirty = true;
+ applyRouting(true);
+ return true;
+ }
+
+ /**
+ * Disable all NFC adapter functions.
+ * Does not toggle preferences.
+ */
+ boolean disableInternal() {
+ if (mState == NfcAdapter.STATE_OFF) {
+ return true;
+ }
+ Log.i(TAG, "Disabling NFC");
+ updateState(NfcAdapter.STATE_TURNING_OFF);
+
+ /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog.
+ * Implemented with a new thread (instead of a Handler or AsyncTask),
+ * because the UI Thread and AsyncTask thread-pools can also get hung
+ * when the NFC controller stops responding */
+ WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS);
+ watchDog.start();
+
+ if (mIsHceCapable) {
+ mCardEmulationManager.onNfcDisabled();
+ }
+
+ mP2pLinkManager.enableDisable(false, false);
+
+ /* The NFC-EE may still be opened by another process,
+ * and a transceive() could still be in progress on
+ * another Binder thread.
+ * Give it a while to finish existing operations
+ * before we close it.
+ */
+ Long startTime = SystemClock.elapsedRealtime();
+ do {
+ synchronized (NfcService.this) {
+ if (mOpenEe == null)
+ break;
+ }
+ try {
+ Thread.sleep(WAIT_FOR_NFCEE_POLL_MS);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ } while (SystemClock.elapsedRealtime() - startTime < WAIT_FOR_NFCEE_OPERATIONS_MS);
+
+ synchronized (NfcService.this) {
+ if (mOpenEe != null) {
+ try {
+ _nfcEeClose(-1, mOpenEe.binder);
+ } catch (IOException e) { }
+ }
+ }
+
+ // Stop watchdog if tag present
+ // A convenient way to stop the watchdog properly consists of
+ // disconnecting the tag. The polling loop shall be stopped before
+ // to avoid the tag being discovered again.
+ maybeDisconnectTarget();
+
+ mNfcDispatcher.setForegroundDispatch(null, null, null);
+
+ boolean result = mDeviceHost.deinitialize();
+ if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result);
+
+ watchDog.cancel();
+
+ synchronized (NfcService.this) {
+ mCurrentDiscoveryParameters = NfcDiscoveryParameters.getNfcOffParameters();
+ updateState(NfcAdapter.STATE_OFF);
+ }
+
+ releaseSoundPool();
+
+ return result;
+ }
+
+ void updateState(int newState) {
+ synchronized (NfcService.this) {
+ if (newState == mState) {
+ return;
+ }
+ /*Added for Loader service recover during NFC Off/On*/
+ if(newState == NfcAdapter.STATE_ON){
+ NfcAlaService nas = new NfcAlaService();
+ nas.LSReexecute();
+ IntentFilter lsFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+ mContext.registerReceiverAsUser(mAlaReceiver, UserHandle.ALL, lsFilter, null, null);
+ }
+ mState = newState;
+ Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+ intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState);
+ mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
+ }
+ }
+ }
+
+ void saveNfcOnSetting(boolean on) {
+ synchronized (NfcService.this) {
+ mPrefsEditor.putBoolean(PREF_NFC_ON, on);
+ mPrefsEditor.apply();
+ }
+ }
+
+ public void playSound(int sound) {
+ synchronized (this) {
+ if (mSoundPool == null) {
+ Log.w(TAG, "Not playing sound when NFC is disabled");
+ return;
+ }
+ switch (sound) {
+ case SOUND_START:
+ mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f);
+ break;
+ case SOUND_END:
+ mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f);
+ break;
+ case SOUND_ERROR:
+ mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f);
+ break;
+ }
+ }
+ }
+
+ synchronized int getUserId() {
+ return mUserId;
+ }
+
+ void setBeamShareActivityState(boolean enabled) {
+ UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ // Propagate the state change to all user profiles related to the current
+ // user. Note that the list returned by getUserProfiles contains the
+ // current user.
+ List <UserHandle> luh = um.getUserProfiles();
+ for (UserHandle uh : luh){
+ enforceBeamShareActivityPolicy(mContext, uh, enabled);
+ }
+ }
+
+ void enforceBeamShareActivityPolicy(Context context, UserHandle uh,
+ boolean isGlobalEnabled){
+ UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ IPackageManager mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+ boolean isActiveForUser =
+ (!um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM, uh)) &&
+ isGlobalEnabled;
+ if (DBG){
+ Log.d(TAG, "Enforcing a policy change on user: " + uh +
+ ", isActiveForUser = " + isActiveForUser);
+ }
+ try {
+ mIpm.setComponentEnabledSetting(new ComponentName(
+ BeamShareActivity.class.getPackageName$(),
+ BeamShareActivity.class.getName()),
+ isActiveForUser ?
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP,
+ uh.getIdentifier());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to change Beam status for user " + uh);
+ }
+ }
+
+ final class NfcAdapterService extends INfcAdapter.Stub {
+ @Override
+ public boolean enable() throws RemoteException {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ int val = mDeviceHost.GetDefaultSE();
+ Log.i(TAG, "getDefaultSE " + val);
+
+ saveNfcOnSetting(true);
+
+ if (mIsAirplaneSensitive && isAirplaneModeOn()) {
+ if (!mIsAirplaneToggleable) {
+ Log.i(TAG, "denying enable() request (airplane mode)");
+ return false;
+ }
+ // Make sure the override survives a reboot
+ mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true);
+ mPrefsEditor.apply();
+ }
+ new EnableDisableTask().execute(TASK_ENABLE);
+
+ return true;
+ }
+
+
+
+ @Override
+ public boolean disable(boolean saveState) throws RemoteException {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ Log.d(TAG,"Disabling Nfc.");
+
+ //Check if this a device shutdown or Nfc only Nfc disable.
+ if(!mPowerShutDown)
+ {
+ Log.i(TAG, "Disabling NFC Disabling ESE/UICC");
+ mDeviceHost.doSetScreenOrPowerState(ScreenStateHelper.POWER_STATE_OFF);
+ //Since only Nfc is getting disabled so disable CE from EE.
+ mDeviceHost.doDeselectSecureElement(UICC_ID_TYPE);
+ mDeviceHost.doDeselectSecureElement(SMART_MX_ID_TYPE);
+ } else {
+ Log.i(TAG, "Power off : Disabling NFC Disabling ESE/UICC");
+ mPowerShutDown = false;
+ mDeviceHost.doSetScreenOrPowerState(ScreenStateHelper.POWER_STATE_ON);
+ mCardEmulationManager.onPreferredForegroundServiceChanged(null);
+ }
+
+ if (saveState) {
+ saveNfcOnSetting(false);
+ }
+
+ new EnableDisableTask().execute(TASK_DISABLE);
+
+ return true;
+ }
+
+ @Override
+ public void pausePolling(int timeoutInMs) {
+ NfcPermissions.enforceAdminPermissions(mContext);
+
+ if (timeoutInMs <= 0 || timeoutInMs > MAX_POLLING_PAUSE_TIMEOUT) {
+ Log.e(TAG, "Refusing to pause polling for " + timeoutInMs + "ms.");
+ return;
+ }
+
+ synchronized (NfcService.this) {
+ mPollingPaused = true;
+ mDeviceHost.disableDiscovery();
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_RESUME_POLLING), timeoutInMs);
+ }
+ }
+
+ @Override
+ public void resumePolling() {
+ NfcPermissions.enforceAdminPermissions(mContext);
+
+ synchronized (NfcService.this) {
+ if (!mPollingPaused) {
+ return;
+ }
+
+ mHandler.removeMessages(MSG_RESUME_POLLING);
+ mPollingPaused = false;
+ new ApplyRoutingTask().execute();
+ }
+ }
+
+ @Override
+ public boolean isNdefPushEnabled() throws RemoteException {
+ synchronized (NfcService.this) {
+ return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled;
+ }
+ }
+
+ @Override
+ public boolean enableNdefPush() throws RemoteException {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ synchronized (NfcService.this) {
+ if (mIsNdefPushEnabled) {
+ return true;
+ }
+ Log.i(TAG, "enabling NDEF Push");
+ mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true);
+ mPrefsEditor.apply();
+ mIsNdefPushEnabled = true;
+ setBeamShareActivityState(true);
+ if (isNfcEnabled()) {
+ mP2pLinkManager.enableDisable(true, true);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean disableNdefPush() throws RemoteException {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ synchronized (NfcService.this) {
+ if (!mIsNdefPushEnabled) {
+ return true;
+ }
+ Log.i(TAG, "disabling NDEF Push");
+ mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false);
+ mPrefsEditor.apply();
+ mIsNdefPushEnabled = false;
+ setBeamShareActivityState(false);
+ if (isNfcEnabled()) {
+ mP2pLinkManager.enableDisable(false, true);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void setForegroundDispatch(PendingIntent intent,
+ IntentFilter[] filters, TechListParcel techListsParcel) {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ // Short-cut the disable path
+ if (intent == null && filters == null && techListsParcel == null) {
+ mNfcDispatcher.setForegroundDispatch(null, null, null);
+ return;
+ }
+
+ // Validate the IntentFilters
+ if (filters != null) {
+ if (filters.length == 0) {
+ filters = null;
+ } else {
+ for (IntentFilter filter : filters) {
+ if (filter == null) {
+ throw new IllegalArgumentException("null IntentFilter");
+ }
+ }
+ }
+ }
+
+ // Validate the tech lists
+ String[][] techLists = null;
+ if (techListsParcel != null) {
+ techLists = techListsParcel.getTechLists();
+ }
+
+ mNfcDispatcher.setForegroundDispatch(intent, filters, techLists);
+ }
+
+ @Override
+ public void setAppCallback(IAppCallback callback) {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ // don't allow Beam for managed profiles, or devices with a device owner or policy owner
+ UserInfo userInfo = mUserManager.getUserInfo(UserHandle.getCallingUserId());
+ if(!mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_OUTGOING_BEAM, userInfo.getUserHandle())) {
+ mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid());
+ } else if (DBG) {
+ Log.d(TAG, "Disabling default Beam behavior");
+ }
+ }
+
+ @Override
+ public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ return mExtrasService;
+ }
+
+ @Override
+ public void verifyNfcPermission() {
+ NfcPermissions.enforceUserPermissions(mContext);
+ }
+
+ @Override
+ public void invokeBeam() {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ if (mForegroundUtils.isInForeground(Binder.getCallingUid())) {
+ mP2pLinkManager.onManualBeamInvoke(null);
+ } else {
+ Log.e(TAG, "Calling activity not in foreground.");
+ }
+ }
+
+ @Override
+ public void invokeBeamInternal(BeamShareData shareData) {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ Message msg = Message.obtain();
+ msg.what = MSG_INVOKE_BEAM;
+ msg.obj = shareData;
+ // We have to send this message delayed for two reasons:
+ // 1) This is an IPC call from BeamShareActivity, which is
+ // running when the user has invoked Beam through the
+ // share menu. As soon as BeamShareActivity closes, the UI
+ // will need some time to rebuild the original Activity.
+ // Waiting here for a while gives a better chance of the UI
+ // having been rebuilt, which means the screenshot that the
+ // Beam animation is using will be more accurate.
+ // 2) Similarly, because the Activity that launched BeamShareActivity
+ // with an ACTION_SEND intent is now in paused state, the NDEF
+ // callbacks that it has registered may no longer be valid.
+ // Allowing the original Activity to resume will make sure we
+ // it has a chance to re-register the NDEF message / callback,
+ // so we share the right data.
+ //
+ // Note that this is somewhat of a hack because the delay may not actually
+ // be long enough for 2) on very slow devices, but there's no better
+ // way to do this right now without additional framework changes.
+ mHandler.sendMessageDelayed(msg, INVOKE_BEAM_DELAY_MS);
+ }
+
+ @Override
+ public INfcTag getNfcTagInterface() throws RemoteException {
+ return mNfcTagService;
+ }
+
+ @Override
+ public INfcCardEmulation getNfcCardEmulationInterface() {
+ if (mIsHceCapable) {
+ return mCardEmulationManager.getNfcCardEmulationInterface();
+ } else {
+ return null;
+ }
+ }
+
+
+ @Override
+ public int getState() throws RemoteException {
+ synchronized (NfcService.this) {
+ return mState;
+ }
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ NfcService.this.dump(fd, pw, args);
+ }
+
+ @Override
+ public void dispatch(Tag tag) throws RemoteException {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ mNfcDispatcher.dispatchTag(tag);
+ }
+
+ @Override
+ public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ mDeviceHost.setP2pInitiatorModes(initiatorModes);
+ mDeviceHost.setP2pTargetModes(targetModes);
+ applyRouting(true);
+ }
+
+ @Override
+ public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras)
+ throws RemoteException {
+ synchronized (NfcService.this) {
+ if (flags != 0) {
+ try {
+ mReaderModeParams = new ReaderModeParams();
+ mReaderModeParams.callback = callback;
+ mReaderModeParams.flags = flags;
+ mReaderModeParams.presenceCheckDelay = extras != null
+ ? (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY,
+ DEFAULT_PRESENCE_CHECK_DELAY))
+ : DEFAULT_PRESENCE_CHECK_DELAY;
+ binder.linkToDeath(mReaderModeDeathRecipient, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote binder has already died.");
+ return;
+ }
+ } else {
+ try {
+ mReaderModeParams = null;
+ binder.unlinkToDeath(mReaderModeDeathRecipient, 0);
+ } catch (NoSuchElementException e) {
+ Log.e(TAG, "Reader mode Binder was never registered.");
+ }
+ }
+ Log.e(TAG, "applyRouting -4");
+ applyRouting(false);
+ }
+ }
+
+
+ @Override
+ public void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, int[] techList) {
+ NfcPermissions.enforceAdminPermissions(mContext);
+
+ int lockscreenPollMask = computeLockscreenPollMask(techList);
+ synchronized (NfcService.this) {
+ mNfcUnlockManager.addUnlockHandler(unlockHandler, lockscreenPollMask);
+ }
+
+ applyRouting(false);
+ }
+
+ @Override
+ public void removeNfcUnlockHandler(INfcUnlockHandler token) throws RemoteException {
+ synchronized (NfcService.this) {
+ mNfcUnlockManager.removeUnlockHandler(token.asBinder());
+ }
+
+ applyRouting(false);
+ }
+ private int computeLockscreenPollMask(int[] techList) {
+
+ Map<Integer, Integer> techCodeToMask = new HashMap<Integer, Integer>();
+
+ techCodeToMask.put(TagTechnology.NFC_A, NfcService.NFC_POLL_A);
+ techCodeToMask.put(TagTechnology.NFC_B, NfcService.NFC_POLL_B);
+ techCodeToMask.put(TagTechnology.NFC_V, NfcService.NFC_POLL_ISO15693);
+ techCodeToMask.put(TagTechnology.NFC_F, NfcService.NFC_POLL_F);
+ techCodeToMask.put(TagTechnology.NFC_BARCODE, NfcService.NFC_POLL_KOVIO);
+ techCodeToMask.put(TagTechnology.MIFARE_CLASSIC, NfcService.NFC_POLL_A);
+ techCodeToMask.put(TagTechnology.MIFARE_ULTRALIGHT, NfcService.NFC_POLL_A);
+
+ int mask = 0;
+
+ for (int i = 0; i < techList.length; i++) {
+ if (techCodeToMask.containsKey(techList[i])) {
+ mask |= techCodeToMask.get(techList[i]).intValue();
+ }
+ }
+
+ return mask;
+ }
+ @Override
+ public INxpNfcAdapter getNxpNfcAdapterInterface() {
+ return mNxpNfcAdapter;
+ }
+ }
+ final class NxpNfcAdapterService extends INxpNfcAdapter.Stub {
+ @Override
+ public INxpNfcAdapterExtras getNxpNfcAdapterExtrasInterface() throws RemoteException {
+ return mNxpExtrasService;
+ }
+ @Override
+ public IeSEClientServicesAdapter getNfcEseClientServicesAdapterInterface() {
+ if(mEseClientServicesAdapter == null){
+ mEseClientServicesAdapter = new EseClientServicesAdapter();
+ }
+ return mEseClientServicesAdapter;
+ }
+
+ //GSMA Changes
+ @Override
+ public INxpNfcController getNxpNfcControllerInterface() {
+ return mNxpNfcController.getNxpNfcControllerInterface();
+ }
+
+ @Override
+ public INfcDta getNfcDtaInterface() {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ //begin
+ if(mDtaService == null){
+ mDtaService = new NfcDtaService();
+ }
+ //end
+ return mDtaService;
+ }
+ @Override
+ public INfcVzw getNfcVzwInterface() {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ //begin
+ if(mVzwService == null){
+ mVzwService = new NfcVzwService();
+ }
+ //end
+ return mVzwService;
+ }
+
+ @Override
+ public int setEmvCoPollProfile(boolean enable, int route) throws RemoteException {
+ return mDeviceHost.setEmvCoPollProfile(enable, route);
+ }
+
+ @Override
+ public int[] getSecureElementList(String pkg) throws RemoteException {
+ NfcService.this.enforceNfcSeAdminPerm(pkg);
+
+ int[] list = null;
+ if (isNfcEnabled()) {
+ list = mDeviceHost.doGetSecureElementList();
+ }
+ return list;
+ }
+
+ @Override
+ public int[] getActiveSecureElementList(String pkg) throws RemoteException {
+ NfcService.this.enforceNfcSeAdminPerm(pkg);
+
+ int[] list = null;
+ if (isNfcEnabled()) {
+ list = mDeviceHost.doGetActiveSecureElementList();
+ }
+ for(int i=0; i< list.length; i++) {
+ Log.d(TAG, "Active element = "+ list[i]);
+ }
+ return list;
+ }
+
+ public INxpNfcAccessExtras getNxpNfcAccessExtrasInterface(String pkg) {
+ NfcService.this.enforceNfcSccAdminPerm(pkg);
+ Log.d(TAG, "getNxpNfcAccessExtrasInterface1");
+ if(mNfcAccessExtrasService == null){
+ mNfcAccessExtrasService = new NfcAccessExtrasService();
+ }
+ return mNfcAccessExtrasService;
+ }
+
+ @Override
+ public int getSelectedSecureElement(String pkg) throws RemoteException {
+ NfcService.this.enforceNfcSeAdminPerm(pkg);
+ return mSelectedSeId;
+ }
+ @Override
+ public int deselectSecureElement(String pkg) throws RemoteException {
+ NfcService.this.enforceNfcSeAdminPerm(pkg);
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return ErrorCodes.ERROR_NOT_INITIALIZED;
+ }
+
+ if (mSelectedSeId == 0) {
+ return ErrorCodes.ERROR_NO_SE_CONNECTED;
+ }
+
+ if (mSelectedSeId != ALL_SE_ID_TYPE/* SECURE_ELEMENT_ALL */) {
+ mDeviceHost.doDeselectSecureElement(mSelectedSeId);
+ } else {
+
+ /* Get SE List */
+ int[] Se_list = mDeviceHost.doGetSecureElementList();
+
+ for (int i = 0; i < Se_list.length; i++) {
+ mDeviceHost.doDeselectSecureElement(Se_list[i]);
+ }
+
+ // mDeviceHost.doSetMultiSEState(false);
+ }
+ mNfcSecureElementState = false;
+ mSelectedSeId = 0;
+
+ /* store preference */
+ mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, false);
+ mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, 0);
+ mPrefsEditor.apply();
+
+ return ErrorCodes.SUCCESS;
+ }
+
+
+
+
+
+ @Override
+ public void storeSePreference(int seId) {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ /* store */
+ Log.d(TAG, "SE Preference stored");
+ mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true);
+ mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, seId);
+ mPrefsEditor.apply();
+ }
+
+ @Override
+ public int selectSecureElement(String pkg,int seId) throws RemoteException {
+ NfcService.this.enforceNfcSeAdminPerm(pkg);
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return ErrorCodes.ERROR_NOT_INITIALIZED;
+ }
+
+ if (mSelectedSeId == seId) {
+ return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
+ }
+
+ if (mSelectedSeId != 0) {
+ return ErrorCodes.ERROR_SE_CONNECTED;
+ }
+ /* Get SE List */
+ int[] Se_list = mDeviceHost.doGetSecureElementList();
+
+ mSelectedSeId = seId;
+ if (seId != ALL_SE_ID_TYPE/* SECURE_ELEMENT_ALL */) {
+ mDeviceHost.doSelectSecureElement(mSelectedSeId);
+ } else {
+ if (Se_list.length > 1) {
+ for (int i = 0; i < Se_list.length; i++) {
+ mDeviceHost.doSelectSecureElement(Se_list[i]);
+ try{
+ //Delay b/w two SE selection.
+ Thread.sleep(200);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ /* store */
+ mPrefsEditor.putBoolean(PREF_SECURE_ELEMENT_ON, true);
+ mPrefsEditor.putInt(PREF_SECURE_ELEMENT_ID, mSelectedSeId);
+ mPrefsEditor.apply();
+
+ mNfcSecureElementState = true;
+
+ return ErrorCodes.SUCCESS;
+ }
+
+ public void MifareDesfireRouteSet(int routeLoc, boolean fullPower, boolean lowPower, boolean noPower)
+ throws RemoteException
+ {
+ int protoRouteEntry = 0;
+ protoRouteEntry=((routeLoc & 0x03)== 0x01) ? (0x01 << 3) : (((routeLoc & 0x03) == 0x02) ? (0x01 << 4) : 0x00) ;
+ protoRouteEntry |= ((fullPower ? 0x01 : 0) | (lowPower ? 0x01 << 1 :0 ) | (noPower ? 0x01 << 2 :0) );
+ mPrefsEditor = mPrefs.edit();
+ mPrefsEditor.putInt("PREF_MIFARE_DESFIRE_PROTO_ROUTE_ID", protoRouteEntry);
+ mPrefsEditor.commit();
+ Log.i(TAG,"MifareDesfireRouteSet function in");
+ commitRouting();
+ }
+
+ public void DefaultRouteSet(int routeLoc, boolean fullPower, boolean lowPower, boolean noPower)
+ throws RemoteException
+ {
+ if (mIsHceCapable) {
+ int protoRouteEntry = 0;
+ protoRouteEntry=((routeLoc & 0x03)== 0x01) ? (0x01 << 3) : (((routeLoc & 0x03) == 0x02) ? (0x01 << 4) : 0x00) ;
+ protoRouteEntry |= ((fullPower ? 0x01 : 0) | (lowPower ? 0x01 << 1 :0 ) | (noPower ? 0x01 << 2 :0));
+ if(GetDefaultRouteLoc() != routeLoc)
+ {
+ mPrefsEditor = mPrefs.edit();
+ mPrefsEditor.putInt("PREF_SET_DEFAULT_ROUTE_ID", protoRouteEntry );
+ mPrefsEditor.commit();
+ mIsRouteForced = true;
+ if (mIsHceCapable) {
+ mAidRoutingManager.onNfccRoutingTableCleared();
+ mCardEmulationManager.onRoutingTableChanged();
+ }
+ mIsRouteForced = false;
+ /*As commit routing is already taken care
+ in onRoutingTableChanged once*/
+ //commitRouting();
+ }
+ }
+ else{
+ Log.i(TAG,"DefaultRoute can not be set. mIsHceCapable = flase");
+ }
+ }
+
+ public void MifareCLTRouteSet(int routeLoc, boolean fullPower, boolean lowPower, boolean noPower)
+ throws RemoteException
+ {
+ int techRouteEntry=0;
+ techRouteEntry=((routeLoc & 0x03)== 0x01) ? (0x01 << 3) : (((routeLoc & 0x03) == 0x02) ? (0x01 << 4) : 0x00) ;
+ techRouteEntry |= ((fullPower ? 0x01 : 0) | (lowPower ? 0x01 << 1 :0 ) | (noPower ? 0x01 << 2 :0) );
+ techRouteEntry |=0x20;
+ mPrefsEditor = mPrefs.edit();
+ mPrefsEditor.putInt("PREF_MIFARE_CLT_ROUTE_ID", techRouteEntry);
+ mPrefsEditor.commit();
+ commitRouting();
+ }
+ @Override
+ public byte[] getFWVersion()
+ {
+ byte[] buf = new byte[2];
+ Log.i(TAG, "Starting getFwVersion");
+ int fwver = mDeviceHost.getFWVersion();
+ buf[0] = (byte)((fwver&0xFF00)>>8);
+ buf[1] = (byte)((fwver&0xFF));
+ Log.i(TAG, "Firmware version is 0x"+ buf[0]+" 0x"+buf[1]);
+ return buf;
+ }
+
+ @Override
+ public Map<String,Integer> getServicesAidCacheSize(int userId, String category){
+ return mCardEmulationManager.getServicesAidCacheSize(userId, category);
+ }
+ @Override
+ public int getSeInterface(int type) throws RemoteException {
+ return mDeviceHost.doGetSeInterface(type);
+ }
+
+// @Override
+// public boolean setVzwAidList(RouteEntry[] entries) throws RemoteException {
+// Log.i(TAG,"setVzwAidList - enter");
+//
+// if(mIsSmartCardServiceSupported == false) {
+// return false;
+// }
+//
+// Log.i(TAG,"setVzwAidList - entries length = " + entries.length);
+// mVzwFilterList = new HashMap<String, RouteEntry>(entries.length);
+//
+// for (int i = 0; i < entries.length; i++) {
+// RouteEntry routeEntry = entries[i];
+// Log.i(TAG,"AID " + toHexString(routeEntry.getAid(),0,routeEntry.getAid().length).toUpperCase() + " : location " + routeEntry.getLocation() +
+// " : powerstate = " + routeEntry.getPowerState());
+//
+// mVzwFilterList.put(toHexString(routeEntry.getAid(),0,routeEntry.getAid().length).toUpperCase(), routeEntry);
+// }
+//
+// Set<String> aids = mAppsAidCache.keySet();
+// for (Iterator iterator = aids.iterator(); iterator.hasNext();) {
+// String appAid = (String) iterator.next();
+// Log.i(TAG,"APP AID :" + appAid);
+//
+// if(mVzwFilterList.containsKey(appAid)) {
+// Log.i(TAG,"APP AID :" + appAid + " VZW AID");
+//
+// if(mVzwFilterList.get(appAid).isAllowed()) {
+// Log.i(TAG,"APP AID :" + appAid + " VZW AID ALLOWED");
+//
+// /* This is a verizone AID and allowed.*/
+// Message msg = mHandler.obtainMessage();
+// msg.what = MSG_VZW_ROUTE_AID;
+// msg.arg1 = mVzwFilterList.get(appAid).getLocation();
+// msg.arg2 = mVzwFilterList.get(appAid).getPowerState();
+// msg.obj = mVzwFilterList.get(appAid).getAid();
+// //send the msg to os handler.
+// mHandler.sendMessage(msg);
+// } else {
+// Log.i(TAG,"APP AID :" + appAid + " VZW AID NOT ALLOWED");
+// /* This is a verizone AID and NOT allowed.*/
+// /* Ignore this AID.*/
+// }
+// } else {
+// Log.i(TAG,"APP AID :" + appAid + " APP AID ALLOWED");
+//
+// Message msg = mHandler.obtainMessage();
+// msg.what = MSG_VZW_ROUTE_AID;
+//
+// //Non VZW AID, treat normally.
+// msg.arg1 = mAppsAidCache.get(appAid).getLocation();
+// msg.arg2 = mAppsAidCache.get(appAid).getPowerState();
+// msg.obj = mAppsAidCache.get(appAid).getAid();
+// //send the msg to os handler.
+// mHandler.sendMessage(msg);
+//
+// }
+//
+// }
+// mHandler.sendEmptyMessage(MSG_VZW_COMMIT_ROUTING);
+// return true;
+// }
+
+// @Override
+// public void setScreenOffCondition(boolean enable) throws RemoteException{
+//
+// if(mIsSmartCardServiceSupported == false) {
+// return;
+// }
+//
+// if(enable && mScreenState <= SCREEN_STATE_ON_LOCKED) {
+// //Do Nothing. Already taken care by NfcService.
+// } else if(enable == false && mScreenState == SCREEN_STATE_ON_UNLOCKED){
+// //Do Nothing. Already taken care by NfcService.
+// } else {
+// if(enable) {
+// mScreenState = SCREEN_STATE_OFF;
+// new ApplyRoutingTask().execute(Integer.valueOf(mScreenState));
+// } else {
+// mScreenState = SCREEN_STATE_ON_UNLOCKED;
+// new ApplyRoutingTask().execute(Integer.valueOf(mScreenState));
+// }
+//
+// //Never come here.
+// }
+// }
+ }
+
+ final class ReaderModeDeathRecipient implements IBinder.DeathRecipient {
+ @Override
+ public void binderDied() {
+ synchronized (NfcService.this) {
+ if (mReaderModeParams != null) {
+ mReaderModeParams = null;
+ Log.e(TAG, "applyRouting -5");
+ applyRouting(false);
+ }
+ }
+ }
+ }
+
+ final class TagService extends INfcTag.Stub {
+ @Override
+ public int close(int nativeHandle) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag = null;
+
+ if (!isNfcEnabled()) {
+ return ErrorCodes.ERROR_NOT_INITIALIZED;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag != null) {
+ /* Remove the device from the hmap */
+ unregisterObject(nativeHandle);
+ tag.disconnect();
+ return ErrorCodes.SUCCESS;
+ }
+ /* Restart polling loop for notification */
+ Log.e(TAG, "applyRouting -6");
+ applyRouting(true);
+ return ErrorCodes.ERROR_DISCONNECT;
+ }
+
+ @Override
+ public int connect(int nativeHandle, int technology) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag = null;
+
+ if (!isNfcEnabled()) {
+ return ErrorCodes.ERROR_NOT_INITIALIZED;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag == null) {
+ return ErrorCodes.ERROR_DISCONNECT;
+ }
+
+ if (!tag.isPresent()) {
+ return ErrorCodes.ERROR_DISCONNECT;
+ }
+
+ // Note that on most tags, all technologies are behind a single
+ // handle. This means that the connect at the lower levels
+ // will do nothing, as the tag is already connected to that handle.
+ if (tag.connect(technology)) {
+ return ErrorCodes.SUCCESS;
+ } else {
+ return ErrorCodes.ERROR_DISCONNECT;
+ }
+ }
+
+ @Override
+ public int reconnect(int nativeHandle) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag = null;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return ErrorCodes.ERROR_NOT_INITIALIZED;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag != null) {
+ if (tag.reconnect()) {
+ return ErrorCodes.SUCCESS;
+ } else {
+ return ErrorCodes.ERROR_DISCONNECT;
+ }
+ }
+ return ErrorCodes.ERROR_DISCONNECT;
+ }
+
+ @Override
+ public int[] getTechList(int nativeHandle) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return null;
+ }
+
+ /* find the tag in the hmap */
+ TagEndpoint tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag != null) {
+ return tag.getTechList();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isPresent(int nativeHandle) throws RemoteException {
+ TagEndpoint tag = null;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return false;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag == null) {
+ return false;
+ }
+
+ return tag.isPresent();
+ }
+
+ @Override
+ public boolean isNdef(int nativeHandle) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag = null;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return false;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ int[] ndefInfo = new int[2];
+ if (tag == null) {
+ return false;
+ }
+ return tag.checkNdef(ndefInfo);
+ }
+
+ @Override
+ public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
+ throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag = null;
+ byte[] response;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return null;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag != null) {
+ // Check if length is within limits
+ if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) {
+ return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null);
+ }
+ int[] targetLost = new int[1];
+ response = tag.transceive(data, raw, targetLost);
+ int result;
+ if (response != null) {
+ result = TransceiveResult.RESULT_SUCCESS;
+ } else if (targetLost[0] == 1) {
+ result = TransceiveResult.RESULT_TAGLOST;
+ } else {
+ result = TransceiveResult.RESULT_FAILURE;
+ }
+ return new TransceiveResult(result, response);
+ }
+ return null;
+ }
+
+ @Override
+ public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return null;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag != null) {
+ byte[] buf = tag.readNdef();
+ if (buf == null) {
+ return null;
+ }
+
+ /* Create an NdefMessage */
+ try {
+ return new NdefMessage(buf);
+ } catch (FormatException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return ErrorCodes.ERROR_NOT_INITIALIZED;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag == null) {
+ return ErrorCodes.ERROR_IO;
+ }
+
+ if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM;
+
+ if (tag.writeNdef(msg.toByteArray())) {
+ return ErrorCodes.SUCCESS;
+ } else {
+ return ErrorCodes.ERROR_IO;
+ }
+
+ }
+
+ @Override
+ public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return ErrorCodes.ERROR_NOT_INITIALIZED;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag == null) {
+ return ErrorCodes.ERROR_IO;
+ }
+
+ if (tag.makeReadOnly()) {
+ return ErrorCodes.SUCCESS;
+ } else {
+ return ErrorCodes.ERROR_IO;
+ }
+ }
+
+ @Override
+ public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return ErrorCodes.ERROR_NOT_INITIALIZED;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag == null) {
+ return ErrorCodes.ERROR_IO;
+ }
+
+ if (tag.formatNdef(key)) {
+ return ErrorCodes.SUCCESS;
+ } else {
+ return ErrorCodes.ERROR_IO;
+ }
+ }
+
+ @Override
+ public Tag rediscover(int nativeHandle) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ TagEndpoint tag = null;
+
+ // Check if NFC is enabled
+ if (!isNfcEnabled()) {
+ return null;
+ }
+
+ /* find the tag in the hmap */
+ tag = (TagEndpoint) findObject(nativeHandle);
+ if (tag != null) {
+ // For now the prime usecase for rediscover() is to be able
+ // to access the NDEF technology after formatting without
+ // having to remove the tag from the field, or similar
+ // to have access to NdefFormatable in case low-level commands
+ // were used to remove NDEF. So instead of doing a full stack
+ // rediscover (which is poorly supported at the moment anyway),
+ // we simply remove these two technologies and detect them
+ // again.
+ tag.removeTechnology(TagTechnology.NDEF);
+ tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
+ tag.findAndReadNdef();
+ // Build a new Tag object to return
+ Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
+ tag.getTechExtras(), tag.getHandle(), this);
+ return newTag;
+ }
+ return null;
+ }
+
+ @Override
+ public int setTimeout(int tech, int timeout) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+ boolean success = mDeviceHost.setTimeout(tech, timeout);
+ if (success) {
+ return ErrorCodes.SUCCESS;
+ } else {
+ return ErrorCodes.ERROR_INVALID_PARAM;
+ }
+ }
+
+ @Override
+ public int getTimeout(int tech) throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ return mDeviceHost.getTimeout(tech);
+ }
+
+ @Override
+ public void resetTimeouts() throws RemoteException {
+ NfcPermissions.enforceUserPermissions(mContext);
+
+ mDeviceHost.resetTimeouts();
+ }
+
+ @Override
+ public boolean canMakeReadOnly(int ndefType) throws RemoteException {
+ return mDeviceHost.canMakeReadOnly(ndefType);
+ }
+
+ @Override
+ public int getMaxTransceiveLength(int tech) throws RemoteException {
+ return mDeviceHost.getMaxTransceiveLength(tech);
+ }
+
+ @Override
+ public boolean getExtendedLengthApdusSupported() throws RemoteException {
+ return mDeviceHost.getExtendedLengthApdusSupported();
+ }
+ }
+
+ final class NfcJcopService extends IJcopService.Stub{
+
+ public int jcopOsDownload(String pkg) throws RemoteException
+ {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ int status = ErrorCodes.SUCCESS;
+ boolean mode;
+ mode = mDeviceHost.doCheckJcopDlAtBoot();
+ if(mode == false) {
+ Log.i(TAG, "Starting getChipName");
+ int Ver = mDeviceHost.getChipVer();
+ if(Ver == PN66T_ID || Ver == PN65T_ID) {
+ status = mDeviceHost.JCOSDownload();
+ }
+ }
+ else {
+ status = ErrorCodes.ERROR_NOT_SUPPORTED;
+ }
+ return status;
+ }
+ }
+ final class EseClientServicesAdapter extends IeSEClientServicesAdapter.Stub{
+ @Override
+ public IJcopService getJcopService() {
+ if(mJcopService == null){
+ mJcopService = new NfcJcopService();
+ }
+ return mJcopService;
+ }
+ @Override
+ public ILoaderService getLoaderService() {
+ if(mAlaService == null){
+ mAlaService = new NfcAlaService();
+ }
+ return mAlaService;
+ }
+ @Override
+ public INxpExtrasService getNxpExtrasService() {
+ if(mNxpExtras == null){
+ mNxpExtras = new NxpExtrasService();
+ }
+ return mNxpExtras;
+ }
+ };
+
+ final class NfcAlaService extends ILoaderService.Stub{
+ private boolean isRecovery = false;
+ private String appName = null;
+ private String srcIn = null;
+ private String respOut = null;
+ private String status = "false";
+
+ void NfcAlaService()
+ {
+ appName = null;
+ srcIn = null;
+ respOut = null;
+ status = "false";
+ isRecovery = false;
+ }
+ private synchronized void LSReexecute()
+ {
+ byte[] ret = {0x4E,0x02,(byte)0x69,(byte)0x87};
+ byte retry = LS_RETRY_CNT;
+ PrintWriter out= null;
+ BufferedReader br = null;
+ Log.i(TAG, "Enter: NfcAlaService constructor");
+ try{
+ File f = new File(LS_BACKUP_PATH);
+
+ Log.i(TAG, "Enter: NfcAlaService constructor file open");
+ /*If the file does not exists*/
+ if(!(f.isFile()))
+ {
+ Log.i(TAG, "FileNotFound ls backup");
+ out = new PrintWriter(LS_BACKUP_PATH);
+ this.status = "true";
+ out.println("null");
+ out.println("null");
+ out.println("null");
+ out.println("true");
+ out.close();
+ }
+ /*If the file exists*/
+ else
+ {
+ Log.i(TAG, "File Found ls backup");
+ br = new BufferedReader(new FileReader(LS_BACKUP_PATH));
+ this.appName = br.readLine();
+ this.srcIn = br.readLine();
+ this.respOut = br.readLine();
+ this.status = br.readLine();
+ }
+ }catch(FileNotFoundException f)
+ {
+ Log.i(TAG, "FileNotFoundException Raised during LS Initialization");
+ return;
+ }
+ catch(IOException ie)
+ {
+ Log.i(TAG, "IOException Raised during LS Initialization ");
+ return;
+ }
+ finally{
+ try{
+ if(out != null)
+ out.close();
+ if(br != null)
+ br.close();
+ }catch(IOException e)
+ {
+ Log.i(TAG, "IOException Raised during LS Initialization ");
+ return;
+ }
+ }
+ if(this.status.equals("true"))
+ {
+ Log.i(TAG, "LS Script execution completed");
+ }
+ else
+ {
+ Log.i(TAG, "LS Script execution aborted or tear down happened");
+ Log.i(TAG, "Input script path"+ this.srcIn);
+ Log.i(TAG, "Output response path"+ this.respOut);
+ Log.i(TAG, "Application name which invoked LS"+ this.appName);
+ try{
+ File fSrc = new File(this.srcIn);
+ File fRsp = new File(this.respOut);
+ if((fSrc.isFile() && fRsp.isFile()))
+ {
+ byte[] lsAppletStatus = {0x6F,0x00};
+ /*Perform lsExecuteScript on tear down*/
+ WatchDogThread watchDog =
+ new WatchDogThread("Loader service ", INIT_WATCHDOG_LS_MS);
+ watchDog.start();
+ try {
+ mRoutingWakeLock.acquire();
+ try {
+ /*Reset retry counter*/
+ while((retry-- > 0))
+ {
+ Thread.sleep(1000);
+ lsAppletStatus = mNfcAla.doLsGetAppletStatus();
+ if((lsAppletStatus[0]==0x63) && (lsAppletStatus[1]==0x40))
+ {
+ Log.i(TAG, "Started LS recovery since previous session failed");
+ this.isRecovery = true;
+ ret = this.lsExecuteScript(this.srcIn, this.respOut);
+ }
+ else
+ {
+ break;
+ }
+ }
+ } finally {
+ this.isRecovery = false;
+ watchDog.cancel();
+ mRoutingWakeLock.release();
+ }
+ }
+ catch(RemoteException ie)
+ {
+ Log.i(TAG, "LS recovery Exception: ");
+ }
+ lsAppletStatus = mNfcAla.doLsGetAppletStatus();
+ if((lsAppletStatus[0]==(byte)0x90)&&(lsAppletStatus[1]==(byte)0x00))
+ {
+ out = new PrintWriter(LS_BACKUP_PATH);
+ out.println("null");
+ out.println("null");
+ out.println("null");
+ out.println("true");
+ out.close();
+ Log.i(TAG, "Commiting Default Values of Loader Service AS RETRY ENDS: ");
+ }
+ }
+ else
+ {
+ Log.i(TAG, "LS recovery not required");
+ }
+ }catch(InterruptedException re)
+ {
+ /*Retry failed todo*/
+ Log.i(TAG, "RemoteException while LS recovery");
+ }catch(FileNotFoundException re)
+ {
+ /*Retry failed todo*/
+ Log.i(TAG, "InterruptException while LS recovery");
+ }
+ }
+ }
+ private void updateLoaderService() {
+ byte[] ret = {0x4E,0x02,(byte)0x69,(byte)0x87};
+ Log.i(TAG, "Enter: NfcAlaService constructor file open");
+ File f = new File(LS_UPDATE_BACKUP_PATH);
+ /*If the file does not exists*/
+ if((f.isFile()))
+ {
+ Log.i(TAG, "File Found LS update required");
+ WatchDogThread watchDog =
+ new WatchDogThread("LS Update Loader service ", (INIT_WATCHDOG_LS_MS+INIT_WATCHDOG_LS_MS));
+ watchDog.start();
+ try {
+ try {
+ /*Reset retry counter*/
+ {
+ Log.i(TAG, "Started LS update");
+ ret = this.lsExecuteScript(LS_UPDATE_BACKUP_PATH, LS_UPDATE_BACKUP_OUT_PATH);
+ if(ret[2] == (byte)(0x90) && ret[3] == (byte)(0x00))
+ {
+ Log.i(TAG, " LS update successfully completed");
+ f.delete();
+ } else {
+ Log.i(TAG, " LS update failed");
+ }
+ }
+ } finally {
+ watchDog.cancel();
+ }
+ }
+ catch(RemoteException ie)
+ {
+ Log.i(TAG, "LS update recovery Exception: ");
+ }
+ }
+ /*If the file exists*/
+ else
+ {
+ Log.i(TAG, "No LS update");
+ }
+ }
+
+ public byte[] lsExecuteScript( String srcIn, String respOut) throws RemoteException {
+ String pkg_name = getCallingAppPkg(mContext);
+ byte[] sha_data = CreateSHA(pkg_name, 2);
+ byte[] respSW = {0x4e,0x02,0x69,(byte)0x87};
+ InputStream is = null;
+ OutputStream os = null;
+ PrintWriter out = null;
+ FileReader fr = null;
+ byte[] buffer = new byte[1024];
+ int length = 0;
+ String srcBackup = srcIn+"mw";
+ String rspBackup = null;
+ File rspFile = null;
+ if(respOut != null)
+ rspBackup = respOut+"mw";
+ File srcFile = new File(srcBackup);
+ if(respOut != null)
+ rspFile = new File(rspBackup);
+
+
+ /*If Previously Tear down happened before completion of LS execution*/
+ if(this.isRecovery != false)
+ {
+ try{
+ fr = new FileReader(LS_BACKUP_PATH);
+ if(fr != null)
+ {
+ BufferedReader br = new BufferedReader(fr);
+ if(br != null)
+ {
+ String appName = br.readLine();
+ if(appName != null)
+ {
+ sha_data = CreateSHA(appName, 2);
+ pkg_name = appName;
+ }
+ }
+ }
+ }catch(IOException ioe)
+ {
+ Log.i(TAG, "IOException thrown for opening ");
+ }
+ finally{
+ try{
+ if(fr != null)
+ fr.close();
+ }
+ catch(IOException e)
+ {
+ Log.i(TAG, "IOException thrown for opening ");
+ }
+ }
+ }
+ /*Store it in File*/
+ try{
+ out = new PrintWriter(LS_BACKUP_PATH);
+ out.println(pkg_name);
+ out.println(srcIn);
+ out.println(respOut);
+ out.println(false);
+ }catch(IOException fe)
+ {
+ Log.i(TAG, "IOException thrown during clearing ");
+ }
+ finally{
+ if(out != null)
+ out.close();
+ }
+ try{
+ /*To avoid rewriting of backup file*/
+ if(!(this.isRecovery)){
+ is = new FileInputStream(srcIn);
+ os = new FileOutputStream(srcBackup);
+
+ while((length = is.read(buffer))>0)
+ {
+ os.write(buffer,0,length);
+ }
+ if(is != null)is.close();
+ if(os != null)os.close();}
+ Log.i(TAG, "sha_data len : " + sha_data.length);
+ Log.i(TAG, "Calling package APP Name is "+ pkg_name);
+ if(sha_data != null)
+ {
+ respSW = mNfcAla.doLsExecuteScript(srcBackup, rspBackup, sha_data);
+ }
+ /*resp file is not null*/
+ if(respOut != null){
+ is = new FileInputStream(rspBackup);
+ os = new FileOutputStream(respOut);
+ length = 0;
+ while((length = is.read(buffer))>0)
+ {
+ os.write(buffer,0,length);
+ }
+ }
+ if(is != null)is.close();
+ if(os != null)os.close();
+ }catch(IOException ioe)
+ {
+ Log.i(TAG, "LS File not found");
+ }catch(SecurityException se)
+ {
+ Log.i(TAG, "LS File access permission deneied");
+ }
+ finally{
+ byte[] status = mNfcAla.doLsGetStatus();
+ Log.i(TAG, "LS getStatus return SW1 : "+status[0]);
+ Log.i(TAG, "LS getStatus return SW2: "+status[1]);
+ if((status[0]== (byte)0x90) && (status[1] == 0x00))
+ {
+ try{
+ out = new PrintWriter(LS_BACKUP_PATH);
+ out.println("null");
+ out.println("null");
+ out.println("null");
+ out.println("true");
+ }catch(IOException fe)
+ {
+ Log.i(TAG, "FileNotFoundException thrown during clearing ");
+ }
+ finally
+ {
+ if(out != null)
+ out.close();
+ }
+ Log.i(TAG, "COMMITTING THE DEFAULT VALUES OF LS : ");
+ srcFile.delete();
+ rspFile.delete();
+ }
+ else
+ {
+ Log.i(TAG, "NOT COMMITTING THE DEFAULT VALUES OF LS : ");
+ }
+ }
+ return respSW;
+ }
+ public byte[] lsGetVersion()
+ {
+ byte[] respApdu = {0x4e,0x02,0x69,(byte)0x87};
+
+ respApdu = mNfcAla.doLsGetVersion();
+ return respApdu;
+ }
+ public int appletLoadApplet(String pkg, String choice) throws RemoteException {
+ String pkg_name = getCallingAppPkg(mContext);
+ int state = 0;
+ byte[] sha_data = CreateSHA(pkg_name, 1);
+ Log.i(TAG, "sha_data len : " + sha_data.length);
+
+ if(sha_data != null)
+ {
+ state = mNfcAla.doAppletLoadApplet(choice, sha_data);
+ return state;
+ }
+ else
+ return 0xFF;
+ }
+ public int getListofApplets(String pkg, String[] name) throws RemoteException {
+ int cnt = mNfcAla.GetAppletsList(name);
+ Log.i(TAG, "GetListofApplets count : " + cnt);
+ for(int i=0;i<cnt;i++) {
+ Log.i(TAG, "GetListofApplets " + name[i]);
+ }
+
+ return cnt;
+ }
+
+ //TODO: Just Stub for compilation.
+ public byte[] getKeyCertificate() throws RemoteException {
+ return null;
+ }
+
+ };
+
+ // public byte[] getKeyCertificate() throws RemoteException {
+ // return mNfcAla.GetCertificateKey();
+ // }
+ // }
+ final class NxpExtrasService extends INxpExtrasService.Stub {
+ private Bundle writeNoException() {
+ Bundle p = new Bundle();
+ p.putInt("e", 0);
+ return p;
+ }
+
+ private Bundle writeEeException(int exceptionType, String message) {
+ Bundle p = new Bundle();
+ p.putInt("e", exceptionType);
+ p.putString("m", message);
+ return p;
+ }
+
+ @Override
+ public boolean isEnabled()
+ {
+ try {
+ return (mState == NfcAdapter.STATE_ON);
+ } catch (Exception e) {
+ Log.d(TAG, "Exception " + e.getMessage());
+ return false;
+ }
+ }
+
+ @Override
+ public byte[] getSecureElementUid(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ return mDeviceHost.getSecureElementUid();
+ }
+
+ @Override
+ public Bundle open(String pkg, IBinder b) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ Bundle result;
+ int handle = _open(b);
+ if (handle < 0) {
+ result = writeEeException(handle, "NFCEE open exception.");
+ } else {
+ result = writeNoException();
+ }
+ return result;
+ }
+
+ /**
+ * Opens a connection to the secure element.
+ *
+ * @return A handle with a value >= 0 in case of success, or a
+ * negative value in case of failure.
+ */
+ private int _open(IBinder b) {
+ synchronized(NfcService.this) {
+ if (!isNfcEnabled()) {
+ return EE_ERROR_NFC_DISABLED;
+ }
+ if (mInProvisionMode) {
+ // Deny access to the NFCEE as long as the device is being setup
+ return EE_ERROR_IO;
+ }
+ if (mP2pLinkManager.isLlcpActive()) {
+ // Don't allow PN544-based devices to open the SE while the LLCP
+ // link is still up or in a debounce state. This avoids race
+ // conditions in the NXP stack around P2P/SMX switching.
+ return EE_ERROR_EXT_FIELD;
+ }
+ if (mOpenEe != null) {
+ return EE_ERROR_ALREADY_OPEN;
+ }
+
+ boolean restorePolling = false;
+ if (mNfcPollingEnabled) {
+ // Disable polling for tags/P2P when connecting to the SMX
+ // on PN544-based devices. Whenever nfceeClose is called,
+ // the polling configuration will be restored.
+ mDeviceHost.disableDiscovery();
+ mNfcPollingEnabled = false;
+ restorePolling = true;
+ }
+ int handle = doOpenSecureElementConnection();
+ if (handle < 0) {
+
+ if (restorePolling) {
+ mDeviceHost.enableDiscovery(mCurrentDiscoveryParameters, true);
+ mNfcPollingEnabled = true;
+ }
+ return handle;
+ }
+ mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000);
+
+ mOpenEe = new OpenSecureElement(getCallingPid(), handle, b);
+ try {
+ b.linkToDeath(mOpenEe, 0);
+ } catch (RemoteException e) {
+ mOpenEe.binderDied();
+ }
+
+ // Add the calling package to the list of packages that have accessed
+ // the secure element.
+ for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) {
+ mSePackages.add(packageName);
+ }
+
+ return handle;
+ }
+ }
+
+ @Override
+ public Bundle close(String pkg, IBinder binder) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ Bundle result;
+ try {
+ _nfcEeClose(getCallingPid(), binder);
+ result = writeNoException();
+ } catch (IOException e) {
+ result = writeEeException(EE_ERROR_IO, e.getMessage());
+ }
+ return result;
+ }
+ @Override
+ public Bundle transceive(String pkg, byte[] in) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ Bundle result;
+ byte[] out;
+ try {
+ out = _transceive(in);
+ result = writeNoException();
+ result.putByteArray("out", out);
+ } catch (IOException e) {
+ result = writeEeException(EE_ERROR_IO, e.getMessage());
+ }
+ return result;
+ }
+
+ private byte[] _transceive(byte[] data) throws IOException {
+ synchronized(NfcService.this) {
+ if (!isNfcEnabled()) {
+ throw new IOException("NFC is not enabled");
+ }
+ if (mOpenEe == null) {
+ throw new IOException("NFC EE is not open");
+ }
+ if (getCallingPid() != mOpenEe.pid) {
+ throw new SecurityException("Wrong PID");
+ }
+ }
+
+ return doTransceive(mOpenEe.handle, data);
+ }
+ };
+ final class NfcDtaService extends INfcDta.Stub {
+
+ public boolean snepDtaCmd(String cmdType, String serviceName, int serviceSap, int miu, int rwSize, int testCaseId) throws RemoteException
+ {
+ NfcPermissions.enforceAdminPermissions(mContext);
+ if(cmdType.equals(null))
+ return false;
+ if(cmdType.equals("enabledta") && (!mIsDtaMode)) {
+ mDeviceHost.enableDtaMode();
+ mIsDtaMode = true;
+ Log.d(TAG, "DTA Mode is Enabled ");
+ }else if(cmdType.equals("disableDta") && (mIsDtaMode)) {
+ mDeviceHost.disableDtaMode();
+ mIsDtaMode = false;
+ } else if(cmdType.equals("enableserver")) {
+ if(serviceName.equals(null))
+ return false;
+ mP2pLinkManager.enableExtDtaSnepServer(serviceName, serviceSap, miu, rwSize,testCaseId);
+ } else if(cmdType.equals("disableserver")) {
+ mP2pLinkManager.disableExtDtaSnepServer();
+ } else if(cmdType.equals("enableclient")) {
+ if(testCaseId == 0)
+ return false;
+ if(testCaseId>20){
+ mIsShortRecordLayout=true;
+ testCaseId=testCaseId-20;
+ }else{
+ mIsShortRecordLayout=false;
+ }
+ Log.d("testCaseId", ""+testCaseId);
+ mP2pLinkManager.enableDtaSnepClient(serviceName, miu, rwSize, testCaseId);
+ } else if(cmdType.equals("disableclient")) {
+ mP2pLinkManager.disableDtaSnepClient();
+ } else {
+ Log.d(TAG, "Unkown DTA Command");
+ return false;
+ }
+ return true;
+ }
+
+ };
+
+ final class NfcVzwService extends INfcVzw.Stub {
+ @Override
+ public void setScreenOffCondition(boolean enable) throws RemoteException {
+
+ Message msg = mHandler.obtainMessage();
+ msg.what=MSG_SET_SCREEN_STATE;
+ msg.arg1= (enable)?1:0;
+ mHandler.sendMessage(msg);
+
+ }
+
+ @Override
+ public boolean setVzwAidList(RouteEntry[] entries)
+ throws RemoteException {
+ // enforceAdminPerm(mContext);
+ Log.i(TAG, "setVzwAidList enter");
+ Log.i(TAG, "setVzwAidList entries length =" + entries.length);
+ if (mIsHceCapable) {
+ mAidRoutingManager.ClearVzwCache();
+ for (int i = 0; i < entries.length; i++) {
+ RouteEntry routeEntry = entries[i];
+ mAidRoutingManager.UpdateVzwCache(routeEntry.getAid(),
+ routeEntry.getLocation(), routeEntry.getPowerState(),
+ routeEntry.isAllowed());
+
+ Log.i(TAG,
+ "AID" + routeEntry.getAid() + "Location "
+ + routeEntry.getLocation() + "powerstate "
+ + routeEntry.getPowerState());
+ }
+ mAidRoutingManager.onNfccRoutingTableCleared();
+ mCardEmulationManager.onRoutingTableChanged();
+ return true;
+ } else {
+ return false;
+ }
+ // TO-DO
+ }
+
+ };
+
+ void _nfcEeClose(int callingPid, IBinder binder) throws IOException {
+ // Blocks until a pending open() or transceive() times out.
+ //TODO: This is incorrect behavior - the close should interrupt pending
+ // operations. However this is not supported by current hardware.
+
+ synchronized (NfcService.this) {
+ if (!isNfcEnabledOrShuttingDown()) {
+ throw new IOException("NFC adapter is disabled");
+ }
+ if (mOpenEe == null) {
+ throw new IOException("NFC EE closed");
+ }
+ if (callingPid != -1 && callingPid != mOpenEe.pid) {
+ throw new SecurityException("Wrong PID");
+ }
+ if (mOpenEe.binder != binder) {
+ throw new SecurityException("Wrong binder handle");
+ }
+
+ binder.unlinkToDeath(mOpenEe, 0);
+ mDeviceHost.resetTimeouts();
+ doDisconnect(mOpenEe.handle);
+ mOpenEe = null;
+ //Log.e(TAG, "applyRouting -8");
+ //applyRouting(true);
+ }
+ }
+
+ boolean _nfcEeReset() throws IOException {
+ synchronized (NfcService.this) {
+ if (!isNfcEnabledOrShuttingDown()) {
+ throw new IOException("NFC adapter is disabled");
+ }
+ if (mOpenEe == null) {
+ throw new IOException("NFC EE closed");
+ }
+ return mSecureElement.doReset(mOpenEe.handle);
+ }
+ }
+
+ final class NfcAccessExtrasService extends INxpNfcAccessExtras.Stub {
+ public boolean checkChannelAdminAccess(String pkg) throws RemoteException {
+ boolean result = true;
+ try {
+ NfcService.this.enforceNfcSccAdminPerm(pkg);
+ } catch (Exception e) {
+ e.printStackTrace();
+ result = false;
+ }
+ return result;
+ }
+ };
+
+ final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub {
+ private Bundle writeNoException() {
+ Bundle p = new Bundle();
+ p.putInt("e", 0);
+ return p;
+ }
+
+ private Bundle writeEeException(int exceptionType, String message) {
+ Bundle p = new Bundle();
+ p.putInt("e", exceptionType);
+ p.putString("m", message);
+ return p;
+ }
+
+ @Override
+ public Bundle open(String pkg, IBinder b) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ Bundle result;
+ int handle = _open(b);
+ if (handle < 0) {
+ result = writeEeException(handle, "NFCEE open exception.");
+ } else {
+ result = writeNoException();
+ }
+ return result;
+ }
+
+ /**
+ * Opens a connection to the secure element.
+ *
+ * @return A handle with a value >= 0 in case of success, or a
+ * negative value in case of failure.
+ */
+ private int _open(IBinder b) {
+ synchronized(NfcService.this) {
+ if (!isNfcEnabled()) {
+ return EE_ERROR_NFC_DISABLED;
+ }
+ if (mInProvisionMode) {
+ // Deny access to the NFCEE as long as the device is being setup
+ return EE_ERROR_IO;
+ }
+ if (mP2pLinkManager.isLlcpActive()) {
+ // Don't allow PN544-based devices to open the SE while the LLCP
+ // link is still up or in a debounce state. This avoids race
+ // conditions in the NXP stack around P2P/SMX switching.
+ return EE_ERROR_EXT_FIELD;
+ }
+ if (mOpenEe != null) {
+ Log.i(TAG, "SE is Busy. returning..");
+ return EE_ERROR_ALREADY_OPEN;
+ }
+ boolean restorePolling = false;
+ if (mNfcPollingEnabled) {
+ // Disable polling for tags/P2P when connecting to the SMX
+ // on PN544-based devices. Whenever nfceeClose is called,
+ // the polling configuration will be restored.
+ mDeviceHost.disableDiscovery();
+ mNfcPollingEnabled = false;
+ restorePolling = true;
+ }
+
+ int handle = doOpenSecureElementConnection();
+ if (handle < 0) {
+
+ if (restorePolling) {
+ mDeviceHost.enableDiscovery(mCurrentDiscoveryParameters, true);
+ mNfcPollingEnabled = true;
+ }
+ return handle;
+ }
+ mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000);
+ mOpenEe = new OpenSecureElement(getCallingPid(), handle, b);
+ try {
+ b.linkToDeath(mOpenEe, 0);
+ } catch (RemoteException e) {
+ mOpenEe.binderDied();
+ }
+
+ // Add the calling package to the list of packages that have accessed
+ // the secure element.
+ for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) {
+ mSePackages.add(packageName);
+ }
+
+ return handle;
+ }
+ }
+
+ @Override
+ public Bundle close(String pkg, IBinder binder) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ Bundle result;
+ try {
+ _nfcEeClose(getCallingPid(), binder);
+ result = writeNoException();
+ } catch (IOException e) {
+ result = writeEeException(EE_ERROR_IO, e.getMessage());
+ }
+ return result;
+ }
+
+// @Override
+// public boolean reset(String pkg) throws RemoteException {
+// NfcService.this.enforceNfceeAdminPerm(pkg);
+// Bundle result;
+// boolean stat = false;
+// try {
+// stat = _nfcEeReset();
+// result = writeNoException();
+// } catch (IOException e) {
+// result = writeEeException(EE_ERROR_IO, e.getMessage());
+// }
+// return stat;
+// }
+
+ @Override
+ public Bundle transceive(String pkg, byte[] in) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ Bundle result;
+ byte[] out;
+ try {
+ out = _transceive(in);
+ result = writeNoException();
+ result.putByteArray("out", out);
+ } catch (IOException e) {
+ result = writeEeException(EE_ERROR_IO, e.getMessage());
+ }
+ return result;
+ }
+
+ private byte[] _transceive(byte[] data) throws IOException {
+ synchronized(NfcService.this) {
+ if (!isNfcEnabled()) {
+ throw new IOException("NFC is not enabled");
+ }
+ if (mOpenEe == null) {
+ throw new IOException("NFC EE is not open");
+ }
+ if (getCallingPid() != mOpenEe.pid) {
+ throw new SecurityException("Wrong PID");
+ }
+ }
+
+ return doTransceive(mOpenEe.handle, data);
+ }
+
+ //@Override
+ //public Bundle getAtr(String pkg) throws RemoteException {
+ // NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ //Bundle result;
+ //byte[] out;
+ //try {
+ // out = _getAtr();
+ // result = writeNoException();
+ // result.putByteArray("out", out);
+ // } catch (IOException e) {
+ // result = writeEeException(EE_ERROR_IO, e.getMessage());
+ //}
+ //return result;
+ //}
+ //private byte[] _getAtr() throws IOException {
+ // synchronized(NfcService.this) {
+ // if (!isNfcEnabled()) {
+ // throw new IOException("NFC is not enabled");
+ // }
+ //if (mOpenEe == null) {
+ // throw new IOException("NFC EE is not open");
+ // }
+ //if (getCallingPid() != mOpenEe.pid) {
+ // throw new SecurityException("Wrong PID");
+ //}
+ // }
+ //return mSecureElement.doGetAtr(mOpenEe.handle);
+ //}
+
+ @Override
+ public int getCardEmulationRoute(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ return mEeRoutingState;
+ }
+
+ @Override
+ public void setCardEmulationRoute(String pkg, int route) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ mEeRoutingState = route;
+ ApplyRoutingTask applyRoutingTask = new ApplyRoutingTask();
+ applyRoutingTask.execute();
+ try {
+ // Block until route is set
+ applyRoutingTask.get();
+ } catch (ExecutionException e) {
+ Log.e(TAG, "failed to set card emulation mode");
+ } catch (InterruptedException e) {
+ Log.e(TAG, "failed to set card emulation mode");
+ }
+ }
+
+ @Override
+ public void authenticate(String pkg, byte[] token) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ }
+
+ @Override
+ public String getDriverName(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ return mDeviceHost.getName();
+ }
+
+ }
+ final class NxpNfcAdapterExtrasService extends INxpNfcAdapterExtras.Stub {
+ private Bundle writeNoException() {
+ Bundle p = new Bundle();
+ p.putInt("e", 0);
+ return p;
+ }
+
+ private Bundle writeEeException(int exceptionType, String message) {
+ Bundle p = new Bundle();
+ p.putInt("e", exceptionType);
+ p.putString("m", message);
+ return p;
+ }
+ @Override
+
+ public boolean reset(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ Bundle result;
+ boolean stat = false;
+ try {
+ stat = _nfcEeReset();
+ result = writeNoException();
+ } catch (IOException e) {
+ result = writeEeException(EE_ERROR_IO, e.getMessage());
+ }
+ Log.d(TAG,"reset" + stat);
+ return stat;
+ }
+
+ boolean _nfcEeReset() throws IOException {
+ synchronized (NfcService.this) {
+ if (!isNfcEnabledOrShuttingDown()) {
+ throw new IOException("NFC adapter is disabled");
+ }
+ if (mOpenEe == null) {
+ throw new IOException("NFC EE closed");
+ }
+ return mSecureElement.doReset(mOpenEe.handle);
+ }
+ }
+
+ @Override
+ public int getSecureElementTechList(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ return mDeviceHost.doGetSecureElementTechList();
+ }
+
+ @Override
+ public byte[] getSecureElementUid(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ return mDeviceHost.getSecureElementUid();
+ }
+
+ @Override
+ public void notifyCheckCertResult(String pkg, boolean success)
+ throws RemoteException {
+ if (DBG) Log.d(TAG, "notifyCheckCertResult() " + pkg + ", success=" + success);
+
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ //NfcPermissions.enforceAdminPermissions(mContext);
+ mNxpNfcController.setResultForX509Certificates(success);
+/* synchronized (mWaitOMACheckCert) {
+ if (mWaitOMACheckCert != null) {
+ if (success) {
+ mHasOMACert = true;
+ } else {
+ mHasOMACert = false;
+ }
+ mWaitOMACheckCert.notify();
+ }
+ }*/
+ }
+
+ @Override
+ public void deliverSeIntent(String pkg, Intent seIntent)
+ throws RemoteException {
+ Log.d(TAG, "deliverSeIntent() " + pkg + " " + seIntent.getAction());
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ //NfcPermissions.enforceAdminPermissions(mContext);
+ sendMessage(MSG_SE_DELIVER_INTENT, seIntent);
+ }
+
+ @Override
+ public byte[] doGetRouting() throws RemoteException {
+ return mDeviceHost.doGetRouting();
+ }
+
+ @Override
+ public Bundle getAtr(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+
+ Bundle result;
+ byte[] out;
+ try {
+ out = _getAtr();
+ result = writeNoException();
+ result.putByteArray("out", out);
+ } catch (IOException e) {
+ result = writeEeException(EE_ERROR_IO, e.getMessage());
+ }
+ Log.d(TAG,"getAtr result " + result);
+ return result;
+ }
+
+ private byte[] _getAtr() throws IOException {
+ synchronized(NfcService.this) {
+ if (!isNfcEnabled()) {
+ throw new IOException("NFC is not enabled");
+ }
+ if (mOpenEe == null) {
+ throw new IOException("NFC EE is not open");
+ }
+ if (getCallingPid() != mOpenEe.pid) {
+ throw new SecurityException("Wrong PID");
+ }
+ }
+ return mSecureElement.doGetAtr(mOpenEe.handle);
+ }
+
+
+ }
+
+ /** resources kept while secure element is open */
+ private class OpenSecureElement implements IBinder.DeathRecipient {
+ public int pid; // pid that opened SE
+ // binder handle used for DeathReceipient. Must keep
+ // a reference to this, otherwise it can get GC'd and
+ // the binder stub code might create a different BinderProxy
+ // for the same remote IBinder, causing mismatched
+ // link()/unlink()
+ public IBinder binder;
+ public int handle; // low-level handle
+ public OpenSecureElement(int pid, int handle, IBinder binder) {
+ this.pid = pid;
+ this.handle = handle;
+ this.binder = binder;
+ }
+ @Override
+ public void binderDied() {
+ synchronized (NfcService.this) {
+ Log.i(TAG, "Tracked app " + pid + " died");
+ pid = -1;
+ try {
+ _nfcEeClose(-1, binder);
+ } catch (IOException e) { /* already closed */ }
+ }
+ }
+ @Override
+ public String toString() {
+ return new StringBuilder('@').append(Integer.toHexString(hashCode())).append("[pid=")
+ .append(pid).append(" handle=").append(handle).append("]").toString();
+ }
+ }
+
+ boolean isNfcEnabledOrShuttingDown() {
+ synchronized (this) {
+ return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF);
+ }
+ }
+
+ boolean isNfcEnabled() {
+ synchronized (this) {
+ return mState == NfcAdapter.STATE_ON;
+ }
+ }
+
+ class WatchDogThread extends Thread {
+ final Object mCancelWaiter = new Object();
+ final int mTimeout;
+ boolean mCanceled = false;
+
+ public WatchDogThread(String threadName, int timeout) {
+ super(threadName);
+ mTimeout = timeout;
+ }
+
+ @Override
+ public void run() {
+ try {
+ synchronized (mCancelWaiter) {
+ mCancelWaiter.wait(mTimeout);
+ if (mCanceled) {
+ return;
+ }
+ }
+ } catch (InterruptedException e) {
+ // Should not happen; fall-through to abort.
+ Log.w(TAG, "Watchdog thread interruped.");
+ interrupt();
+ }
+ Log.e(TAG, "Watchdog triggered, aborting.");
+ mDeviceHost.doAbort();
+ }
+
+ public synchronized void cancel() {
+ synchronized (mCancelWaiter) {
+ mCanceled = true;
+ mCancelWaiter.notify();
+ }
+ }
+ }
+
+ /* For Toast from background process*/
+
+ public class ToastHandler
+ {
+ // General attributes
+ private Context mContext;
+ private Handler mHandler;
+
+ public ToastHandler(Context _context)
+ {
+ this.mContext = _context;
+ this.mHandler = new Handler();
+ }
+
+ /**
+ * Runs the <code>Runnable</code> in a separate <code>Thread</code>.
+ *
+ * @param _runnable
+ * The <code>Runnable</code> containing the <code>Toast</code>
+ */
+ private void runRunnable(final Runnable _runnable)
+ {
+ Thread thread = new Thread()
+ {
+ public void run()
+ {
+ mHandler.post(_runnable);
+ }
+ };
+
+ thread.start();
+ thread.interrupt();
+ thread = null;
+ }
+
+ public void showToast(final CharSequence _text, final int _duration)
+ {
+ final Runnable runnable = new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ Toast.makeText(mContext, _text, _duration).show();
+ }
+ };
+
+ runRunnable(runnable);
+ }
+ }
+
+ static byte[] hexStringToBytes(String s) {
+ if (s == null || s.length() == 0) return null;
+ int len = s.length();
+ if (len % 2 != 0) {
+ s = '0' + s;
+ len++;
+ }
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i + 1), 16));
+ }
+ return data;
+ }
+
+ static String toHexString(byte[] buffer, int offset, int length) {
+ final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
+ char[] chars = new char[2 * length];
+ for (int j = offset; j < offset + length; ++j) {
+ chars[2 * (j-offset)] = HEX_CHARS[(buffer[j] & 0xF0) >>> 4];
+ chars[2 * (j-offset) + 1] = HEX_CHARS[buffer[j] & 0x0F];
+ }
+ return new String(chars);
+ }
+
+ /**
+ * Read mScreenState and apply NFC-C polling and NFC-EE routing
+ */
+ void applyRouting(boolean force) {
+ Log.d(TAG, "applyRouting - enter force = " + force + " mScreenState = " + mScreenState);
+
+ synchronized (this) {
+ //Since Reader mode during wired mode is supported
+ //enableDiscovery or disableDiscovery is allowed
+ //if (!isNfcEnabledOrShuttingDown() || mOpenEe != null) {
+ if (!isNfcEnabledOrShuttingDown()) {
+ // PN544 cannot be reconfigured while EE is open
+ return;
+ }
+ WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS);
+ if (mInProvisionMode) {
+ mInProvisionMode = Settings.Secure.getInt(mContentResolver,
+ Settings.Global.DEVICE_PROVISIONED, 0) == 0;
+ if (!mInProvisionMode) {
+ // Notify dispatcher it's fine to dispatch to any package now
+ // and allow handover transfers.
+ mNfcDispatcher.disableProvisioningMode();
+ }
+ }
+ // Special case: if we're transitioning to unlocked state while
+ // still talking to a tag, postpone re-configuration.
+ if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && isTagPresent()) {
+ Log.d(TAG, "Not updating discovery parameters, tag connected.");
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESUME_POLLING),
+ APPLY_ROUTING_RETRY_TIMEOUT_MS);
+ return;
+ }
+
+ try {
+ watchDog.start();
+ // Compute new polling parameters
+ NfcDiscoveryParameters newParams = computeDiscoveryParameters(mScreenState);
+ if (force || !newParams.equals(mCurrentDiscoveryParameters)) {
+ if (newParams.shouldEnableDiscovery()) {
+ boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery();
+ mDeviceHost.enableDiscovery(newParams, shouldRestart);
+ } else {
+ mDeviceHost.disableDiscovery();
+ }
+ mCurrentDiscoveryParameters = newParams;
+ } else {
+ Log.d(TAG, "Discovery configuration equal, not updating.");
+ }
+ } finally {
+ watchDog.cancel();
+ }
+ }
+ }
+
+ private NfcDiscoveryParameters computeDiscoveryParameters(int screenState) {
+ // Recompute discovery parameters based on screen state
+ NfcDiscoveryParameters.Builder paramsBuilder = NfcDiscoveryParameters.newBuilder();
+ // Polling
+ if (screenState >= NFC_POLLING_MODE) {
+ // Check if reader-mode is enabled
+ if (mReaderModeParams != null) {
+ int techMask = 0;
+ if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_A) != 0)
+ techMask |= NFC_POLL_A;
+ if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_B) != 0)
+ techMask |= NFC_POLL_B;
+ if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_F) != 0)
+ techMask |= NFC_POLL_F;
+ if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_V) != 0)
+ techMask |= NFC_POLL_ISO15693;
+ if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_BARCODE) != 0)
+ techMask |= NFC_POLL_KOVIO;
+
+ paramsBuilder.setTechMask(techMask);
+ paramsBuilder.setEnableReaderMode(true);
+ } else {
+ paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT);
+ paramsBuilder.setEnableP2p(mIsNdefPushEnabled);
+ }
+ } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mInProvisionMode) {
+ paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT);
+ // enable P2P for MFM/EDU/Corp provisioning
+ paramsBuilder.setEnableP2p(true);
+ } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED &&
+ mNfcUnlockManager.isLockscreenPollingEnabled()) {
+ // For lock-screen tags, no low-power polling
+ paramsBuilder.setTechMask(mNfcUnlockManager.getLockscreenPollMask());
+ paramsBuilder.setEnableLowPowerDiscovery(false);
+ paramsBuilder.setEnableP2p(false);
+ }
+
+ if (mIsHceCapable && mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
+ // Host routing is always enabled at lock screen or later
+ paramsBuilder.setEnableHostRouting(true);
+ }
+ //To make routing table update.
+ if(mIsRoutingTableDirty) {
+ mIsRoutingTableDirty = false;
+ //TODO: Take this logic from L_OSP_EXT [PN547C2]
+ int protoRoute = mPrefs.getInt("PREF_MIFARE_DESFIRE_PROTO_ROUTE_ID", GetDefaultMifareDesfireRouteEntry());
+ int defaultRoute=mPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID", GetDefaultRouteEntry());
+ int techRoute=mPrefs.getInt("PREF_MIFARE_CLT_ROUTE_ID", GetDefaultMifateCLTRouteEntry());
+ Log.d(TAG, "Set default Route Entry");
+ setDefaultRoute(defaultRoute, protoRoute, techRoute);
+ }
+/*
+ //Configure for Felica Routing
+ if(mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mIsFelicaOnHostConfiguring) {
+ mIsFelicaOnHostConfiguring = false;
+// mDeviceHost.disableDiscovery();
+ paramsBuilder.setTechMask(0);
+ paramsBuilder.setEnableHostRouting(false);
+ }
+
+ if(mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mIsFelicaOnHostConfigured) {
+ mIsFelicaOnHostConfigured = false;
+ //mDeviceHost.enableDiscovery();
+ }
+*/
+ return paramsBuilder.build();
+ }
+
+ private boolean isTagPresent() {
+ for (Object object : mObjectMap.values()) {
+ if (object instanceof TagEndpoint) {
+ return ((TagEndpoint) object).isPresent();
+ }
+ }
+ return false;
+ }
+ /**
+ * Disconnect any target if present
+ */
+ void maybeDisconnectTarget() {
+ if (!isNfcEnabledOrShuttingDown()) {
+ return;
+ }
+ Object[] objectsToDisconnect;
+ synchronized (this) {
+ Object[] objectValues = mObjectMap.values().toArray();
+ // Copy the array before we clear mObjectMap,
+ // just in case the HashMap values are backed by the same array
+ objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length);
+ mObjectMap.clear();
+ }
+ for (Object o : objectsToDisconnect) {
+ if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName());
+ if (o instanceof TagEndpoint) {
+ // Disconnect from tags
+ TagEndpoint tag = (TagEndpoint) o;
+ tag.disconnect();
+ } else if (o instanceof NfcDepEndpoint) {
+ // Disconnect from P2P devices
+ NfcDepEndpoint device = (NfcDepEndpoint) o;
+ if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
+ // Remote peer is target, request disconnection
+ device.disconnect();
+ } else {
+ // Remote peer is initiator, we cannot disconnect
+ // Just wait for field removal
+ }
+ }
+ }
+ }
+
+ Object findObject(int key) {
+ synchronized (this) {
+ Object device = mObjectMap.get(key);
+ if (device == null) {
+ Log.w(TAG, "Handle not found");
+ }
+ return device;
+ }
+ }
+
+ void registerTagObject(TagEndpoint tag) {
+ synchronized (this) {
+ mObjectMap.put(tag.getHandle(), tag);
+ }
+ }
+
+ void unregisterObject(int handle) {
+ synchronized (this) {
+ mObjectMap.remove(handle);
+ }
+ }
+
+ /**
+ * For use by code in this process
+ */
+ public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
+ throws LlcpException {
+ return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength);
+ }
+
+ /**
+ * For use by code in this process
+ */
+ public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn)
+ throws LlcpException {
+ return mDeviceHost.createLlcpConnectionlessSocket(sap, sn);
+ }
+
+ /**
+ * For use by code in this process
+ */
+ public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw,
+ int linearBufferLength) throws LlcpException {
+ return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength);
+ }
+
+ public void sendMockNdefTag(NdefMessage msg) {
+ sendMessage(MSG_MOCK_NDEF, msg);
+ }
+
+ public void notifyRoutingTableFull()
+ {
+ //broadcast Aid Routing Table Full intent to the user
+ String ACTION_ROUTING_TABLE_FULL =
+ "com.nxp.action.AID_ROUTING_TABLE_FULL";
+ Intent aidTableFull = new Intent();
+ aidTableFull.setAction(ACTION_ROUTING_TABLE_FULL);
+ if (DBG) {
+ Log.d(TAG, "notify aid routing table full to the user");
+ }
+ mContext.sendBroadcast(aidTableFull);
+ }
+ /**
+ * set default Aid route entry in case application does not configure this route entry
+ */
+ public void setDefaultAidRouteLoc( int defaultAidRouteEntry)
+ {
+ mPrefsEditor = mPrefs.edit();
+ Log.d(TAG, "writing to preferences setDefaultAidRouteLoc :" + defaultAidRouteEntry);
+ mPrefsEditor.putInt("PREF_SET_DEFAULT_ROUTE_ID", (defaultAidRouteEntry << 0x03 )| ROUTE_SWITCH_ON );
+ mPrefsEditor.commit();
+ int defaultRoute=mPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID",0xFF);
+ Log.d(TAG, "reading preferences from user :" + defaultRoute);
+ }
+
+ public int getAidRoutingTableSize ()
+ {
+ int aidTableSize = 0x00;
+ aidTableSize = mDeviceHost.getAidTableSize();
+ return aidTableSize;
+ }
+
+ public void routeAids(String aid, int route, int powerState) {
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_ROUTE_AID;
+ msg.arg1 = route;
+ msg.arg2 = powerState;
+ msg.obj = aid;
+ mHandler.sendMessage(msg);
+ }
+
+ public void unrouteAids(String aid) {
+ sendMessage(MSG_UNROUTE_AID, aid);
+ }
+
+ public void commitRouting() {
+ mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING);
+ }
+ /**
+ * get default Aid route entry in case application does not configure this route entry
+ */
+ public int GetDefaultRouteLoc()
+ {
+ int defaultRouteLoc = mPrefs.getInt("PREF_SET_DEFAULT_ROUTE_ID", GetDefaultRouteEntry()) >> ROUTE_LOC_MASK;
+ Log.d(TAG, "GetDefaultRouteLoc :" + defaultRouteLoc);
+ return defaultRouteLoc ;
+ }
+
+ /**
+ * get default MifareDesfireRoute route entry in case application does not configure this route entry
+ */
+ public int GetDefaultMifareDesfireRouteEntry()
+ {
+ //return ((ROUTE_ID_UICC << ROUTE_LOC_MASK ) | ROUTE_SWITCH_ON | ROUTE_SWITCH_OFF) ;
+ Log.d(TAG, "GetDefaultMifareDesfireRouteEntry :" + mDeviceHost.getDefaultDesfireRoute() );
+ return ((mDeviceHost.getDefaultDesfireRoute() << ROUTE_LOC_MASK ) | ROUTE_SWITCH_ON | ROUTE_SWITCH_OFF) ;
+ }
+ /**
+ * set default Aid route entry in case application does not configure this route entry
+ */
+
+ public int GetDefaultRouteEntry()
+ {
+ int defaultAidRoute = ((mDeviceHost.getDefaultAidRoute()<< ROUTE_LOC_MASK) | ROUTE_SWITCH_ON);
+ Log.d(TAG, "GetDefaultRouteEntry :" + defaultAidRoute );
+ return defaultAidRoute;
+ }
+
+ /**
+ * get default MifateCLT route entry in case application does not configure this route entry
+ */
+ public int GetDefaultMifateCLTRouteEntry()
+ {
+ //return ((ROUTE_ID_UICC << ROUTE_LOC_MASK ) | ROUTE_SWITCH_ON | ROUTE_SWITCH_OFF | (TECH_TYPE_A << TECH_TYPE_MASK)) ;
+ Log.d(TAG, "getDefaultMifareCLTRoute :" + mDeviceHost.getDefaultMifareCLTRoute() );
+ return ((mDeviceHost.getDefaultMifareCLTRoute() << ROUTE_LOC_MASK ) | ROUTE_SWITCH_ON | ROUTE_SWITCH_OFF | (TECH_TYPE_A << TECH_TYPE_MASK)) ;
+ }
+
+ public boolean setDefaultRoute(int defaultRouteEntry, int defaultProtoRouteEntry, int defaultTechRouteEntry) {
+ boolean ret = mDeviceHost.setDefaultRoute(defaultRouteEntry, defaultProtoRouteEntry, defaultTechRouteEntry);
+ return ret;
+ }
+
+ public int getDefaultRoute() {
+ return mPrefs.getInt(PREF_DEFAULT_ROUTE_ID, DEFAULT_ROUTE_ID_DEFAULT);
+ }
+
+
+ public void commitingFelicaRouting() {
+ mHandler.sendEmptyMessage(MSG_COMMITINF_FELICA_ROUTING);
+ }
+
+ public void commitedFelicaRouting() {
+ mHandler.sendEmptyMessage(MSG_COMMITED_FELICA_ROUTING);
+ }
+
+
+ public void routeNfcid2(String nfcid2, String syscode, String optparam) {
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_ROUTE_NFCID2;
+ Bundle extras = new Bundle();
+ extras.putString(Nfcid2RoutingCache.EXTRA_NFCID2, nfcid2);
+ extras.putString(Nfcid2RoutingCache.EXTRA_SYSCODE, syscode);
+ extras.putString(Nfcid2RoutingCache.EXTRA_OPTPARAM, optparam);
+ msg.obj = extras;
+ mHandler.sendMessage(msg);
+ }
+
+ public void unrouteNfcid2(String nfcid2) {
+ Message msg = mHandler.obtainMessage();
+ msg.what = MSG_UNROUTE_NFCID2;
+ msg.obj = nfcid2;
+ mHandler.sendMessage(msg);
+ }
+
+ public void clearRouting() {
+ mHandler.sendEmptyMessage(MSG_CLEAR_ROUTING);
+ }
+
+ public boolean isVzwFeatureEnabled(){
+ return mDeviceHost.isVzwFeatureEnabled();
+ }
+
+ public boolean sendData(byte[] data) {
+ return mDeviceHost.sendRawFrame(data);
+ }
+
+ public int getDefaultSecureElement() {
+ int[] seList = mDeviceHost.doGetSecureElementList();
+ if ( seList == null || seList.length != 1) {
+ //use default value
+ return -1;
+ } else {
+ return seList[0];
+ }
+ }
+
+ public void etsiStartConfig(int eeHandle) {
+ Log.d(TAG, "etsiStartConfig Enter");
+
+ Log.d(TAG, "etsiStartConfig : etsiInitConfig");
+ mDeviceHost.etsiInitConfig();
+
+ Log.d(TAG, "etsiStartConfig : disableDiscovery");
+ mDeviceHost.disableDiscovery();
+
+ Log.d(TAG, "etsiStartConfig : etsiReaderConfig");
+ mDeviceHost.etsiReaderConfig(eeHandle);
+
+ Log.d(TAG, "etsiStartConfig : notifyEEReaderEvent");
+ mDeviceHost.notifyEEReaderEvent(ETSI_READER_REQUESTED);
+
+ Log.d(TAG, "etsiStartConfig : setEtsiReaederState");
+ mDeviceHost.setEtsiReaederState(STATE_SE_RDR_MODE_STARTED);
+ //broadcast SWP_READER_ACTIVATED evt
+ Intent SWPReaderRequestedIntent = new Intent();
+ SWPReaderRequestedIntent.setAction(NxpConstants.ACTION_SWP_READER_REQUESTED);
+ if (DBG) {
+ Log.d(TAG, "SWP READER - Requested");
+ }
+ mContext.sendBroadcast(SWPReaderRequestedIntent);
+
+ Log.d(TAG, "etsiStartConfig : enableDiscovery");
+ mDeviceHost.enableDiscovery(mCurrentDiscoveryParameters, true);
+
+ Log.d(TAG, "etsiStartConfig Exit");
+ }
+
+ public void etsiStopConfig(int discNtfTimeout) {
+ Log.d(TAG, "etsiStopConfig Enter");
+ if( mDeviceHost.getEtsiReaederState() == STATE_SE_RDR_MODE_STOP_IN_PROGRESS)
+ {
+ Log.d(TAG, "Attempting etsiStopConfig while STATE_SE_RDR_MODE_STOP_IN_PROGRESS. Returning..");
+ return;
+ }
+ ETSI_STOP_CONFIG = true;
+ TagRemoveTask tagRemoveTask = new TagRemoveTask();
+ tagRemoveTask.execute(discNtfTimeout);
+ Log.d(TAG, "etsiStopConfig : etsiInitConfig");
+ mDeviceHost.etsiInitConfig();
+
+ //mDeviceHost.setEtsiReaederState(STATE_SE_RDR_MODE_STOPPED);
+ Log.d(TAG, "etsiStopConfig : disableDiscovery");
+ mDeviceHost.disableDiscovery();
+
+ if(mDeviceHost.getEtsiReaederState() == STATE_SE_RDR_MODE_STOPPED)
+ {
+ Log.d(TAG, "etsiStopConfig :etsi reader already Stopped. Returning..");
+ ETSI_STOP_CONFIG = false;
+ return;
+ }
+ Log.d(TAG, "etsiStopConfig : etsiResetReaderConfig");
+ mDeviceHost.etsiResetReaderConfig();
+
+ Log.d(TAG, "etsiStopConfig : notifyEEReaderEvent");
+ mDeviceHost.notifyEEReaderEvent(ETSI_READER_STOP);
+
+ Intent SWPReaderDeActivatedIntent = new Intent();
+
+ //broadcast SWP_READER_DEACTIVATED evt
+ SWPReaderDeActivatedIntent
+ .setAction(NxpConstants.ACTION_SWP_READER_DEACTIVATED);
+ if (DBG) {
+ Log.d(TAG, "SWP READER - DeActivated");
+ }
+ mContext.sendBroadcast(SWPReaderDeActivatedIntent);
+
+ Log.d(TAG, "etsiStopConfig : setEtsiReaederState");
+ mDeviceHost.setEtsiReaederState(STATE_SE_RDR_MODE_STOPPED);
+
+ Log.d(TAG, "etsiStopConfig : enableDiscovery");
+ mDeviceHost.enableDiscovery(mCurrentDiscoveryParameters, true);
+ ETSI_STOP_CONFIG = false;
+
+ Log.d(TAG, "etsiStopConfig : updateScreenState");
+ mDeviceHost.updateScreenState();
+
+ Log.d(TAG, "etsiStopConfig Exit");
+ }
+
+ void sendMessage(int what, Object obj) {
+ Message msg = mHandler.obtainMessage();
+ msg.what = what;
+ msg.obj = obj;
+ mHandler.sendMessage(msg);
+ }
+
+ final class NfcServiceHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ROUTE_AID: {
+ int route = msg.arg1;
+ int power = msg.arg2;
+ String aid = (String) msg.obj;
+ if(aid.endsWith("*")) {
+ String cuttedAid = aid.substring(0, aid.length() - 1);
+ mDeviceHost.routeAid(hexStringToBytes(cuttedAid), route, power, true);
+ } else {
+ mDeviceHost.routeAid(hexStringToBytes(aid), route, power, false);
+ }
+ // Restart polling config
+ break;
+ }
+ case MSG_INVOKE_BEAM: {
+ mP2pLinkManager.onManualBeamInvoke((BeamShareData)msg.obj);
+ break;
+ }
+ case MSG_UNROUTE_AID: {
+ String aid = (String) msg.obj;
+ mDeviceHost.unrouteAid(hexStringToBytes(aid));
+ break;
+ }
+
+ case MSG_ROUTE_NFCID2: {
+ Bundle extras = (Bundle) msg.obj;
+ String nfcid2 = extras.getString(Nfcid2RoutingCache.EXTRA_NFCID2, null);
+ String syscode = extras.getString(Nfcid2RoutingCache.EXTRA_SYSCODE, null);
+ String optcode = extras.getString(Nfcid2RoutingCache.EXTRA_OPTPARAM, null);
+
+ mDeviceHost.routeNfcid2(hexStringToBytes(nfcid2), hexStringToBytes(syscode), hexStringToBytes(optcode));
+ // Restart polling config
+ break;
+ }
+
+ case MSG_UNROUTE_NFCID2: {
+ String nfcid2 = (String) msg.obj;
+ mDeviceHost.unrouteNfcid2(hexStringToBytes(nfcid2));
+ // Restart polling config
+ break;
+ }
+
+ case MSG_COMMITINF_FELICA_ROUTING: {
+ Log.e(TAG, "applyRouting -10");
+ mIsFelicaOnHostConfiguring = true;
+ applyRouting(true);
+ break;
+ }
+
+ case MSG_COMMITED_FELICA_ROUTING: {
+ Log.e(TAG, "applyRouting -11");
+ mIsFelicaOnHostConfigured = true;
+ applyRouting(true);
+ break;
+ }
+
+
+ case MSG_COMMIT_ROUTING: {
+ Log.e(TAG, "applyRouting -9");
+ boolean commit = false;
+ synchronized (NfcService.this) {
+ if (mCurrentDiscoveryParameters.shouldEnableDiscovery()) {
+ commit = true;
+ } else {
+ Log.d(TAG, "Not committing routing because discovery is disabled.");
+ }
+ }
+ if (commit) {
+ mIsRoutingTableDirty = true;
+ applyRouting(false);
+ }
+
+
+ break;
+ }
+ case MSG_CLEAR_ROUTING: {
+ mDeviceHost.clearAidTable();
+ break;
+ }
+
+ case MSG_CHANGE_DEFAULT_ROUTE:
+ Log.d(TAG, "Handler: Change default route");
+ try{
+ mNxpNfcAdapter.DefaultRouteSet(ROUTE_ID_HOST, true, false, false);
+ } catch(RemoteException re) {
+ Log.d(TAG, "NxpNci: onAidRoutingTableFull: Exception to change default route to host!");
+ }
+ break;
+
+ case MSG_MOCK_NDEF: {
+ NdefMessage ndefMsg = (NdefMessage) msg.obj;
+ Bundle extras = new Bundle();
+ extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg);
+ extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0);
+ extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY);
+ extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER);
+ Tag tag = Tag.createMockTag(new byte[]{0x00},
+ new int[]{TagTechnology.NDEF},
+ new Bundle[]{extras});
+ Log.d(TAG, "mock NDEF tag, starting corresponding activity");
+ Log.d(TAG, tag.toString());
+ int dispatchStatus = mNfcDispatcher.dispatchTag(tag);
+ if (dispatchStatus == NfcDispatcher.DISPATCH_SUCCESS) {
+ playSound(SOUND_END);
+ } else if (dispatchStatus == NfcDispatcher.DISPATCH_FAIL) {
+ playSound(SOUND_ERROR);
+ }
+ break;
+ }
+
+ case MSG_SE_DELIVER_INTENT: {
+ Log.d(TAG, "SE DELIVER INTENT");
+ Intent seIntent = (Intent) msg.obj;
+
+ String action = seIntent.getAction();
+ if (action.equals("com.gsma.services.nfc.action.TRANSACTION_EVENT")) {
+ byte[] byteAid = seIntent.getByteArrayExtra("com.android.nfc_extras.extra.AID");
+ byte[] data = seIntent.getByteArrayExtra("com.android.nfc_extras.extra.DATA");
+ String seName = seIntent.getStringExtra("com.android.nfc_extras.extra.SE_NAME");
+ StringBuffer strAid = new StringBuffer();
+ for (int i = 0; i < byteAid.length; i++) {
+ String hex = Integer.toHexString(0xFF & byteAid[i]);
+ if (hex.length() == 1)
+ strAid.append('0');
+ strAid.append(hex);
+ }
+ Intent gsmaIntent = new Intent();
+ gsmaIntent.setAction("com.gsma.services.nfc.action.TRANSACTION_EVENT");
+ if (byteAid != null)
+ gsmaIntent.putExtra("com.gsma.services.nfc.extra.AID", byteAid);
+ if (data != null)
+ gsmaIntent.putExtra("com.gsma.services.nfc.extra.DATA", data);
+
+ //"nfc://secure:0/<seName>/<strAid>"
+ String url = new String ("nfc://secure:0/" + seName + "/" + strAid);
+ gsmaIntent.setData(Uri.parse(url));
+ gsmaIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ gsmaIntent.setPackage(seIntent.getPackage());
+
+ Boolean receptionMode = mNxpNfcController.mMultiReceptionMap.get(seName);
+ if (receptionMode == null)
+ receptionMode = defaultTransactionEventReceptionMode;
+
+ if (receptionMode == multiReceptionMode) {
+ // if multicast reception for GSMA
+ mContext.sendBroadcast(gsmaIntent);
+ } else {
+ // if unicast reception for GSMA
+ try {
+ if (mIsSentUnicastReception == false) {
+ //start gsma
+ gsmaIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(gsmaIntent);
+ mIsSentUnicastReception = true;
+ }
+ } catch (Exception e) {
+ if (DBG) Log.d(TAG, "Exception: " + e.getMessage());
+ }
+ }
+ } else {
+ mContext.sendBroadcast(seIntent);
+ }
+ break;
+ }
+
+ case MSG_NDEF_TAG:
+ if (DBG) Log.d(TAG, "Tag detected, notifying applications");
+ TagEndpoint tag = (TagEndpoint) msg.obj;
+ ReaderModeParams readerParams = null;
+ int presenceCheckDelay = DEFAULT_PRESENCE_CHECK_DELAY;
+ DeviceHost.TagDisconnectedCallback callback =
+ new DeviceHost.TagDisconnectedCallback() {
+ @Override
+ public void onTagDisconnected(long handle) {
+ applyRouting(false);
+ }
+ };
+ synchronized (NfcService.this) {
+ readerParams = mReaderModeParams;
+ }
+ if (readerParams != null) {
+ presenceCheckDelay = readerParams.presenceCheckDelay;
+ if ((readerParams.flags & NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK) != 0) {
+ if (DBG) Log.d(TAG, "Skipping NDEF detection in reader mode");
+ tag.startPresenceChecking(presenceCheckDelay, callback);
+ dispatchTagEndpoint(tag, readerParams);
+ break;
+ }
+ }
+
+ boolean playSound = readerParams == null ||
+ (readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0;
+ if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && playSound) {
+ playSound(SOUND_START);
+ }
+ if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) {
+ // When these tags start containing NDEF, they will require
+ // the stack to deal with them in a different way, since
+ // they are activated only really shortly.
+ // For now, don't consider NDEF on these.
+ if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode");
+ tag.startPresenceChecking(presenceCheckDelay, callback);
+ dispatchTagEndpoint(tag, readerParams);
+ break;
+ }
+ NdefMessage ndefMsg = tag.findAndReadNdef();
+
+ if (ndefMsg != null) {
+ if(tag.getConnectedTechnology() == TagTechnology.NFC_F)
+ {
+ presenceCheckDelay = NFC_F_TRANSCEIVE_PRESENCE_CHECK_DELAY;
+ }
+ tag.startPresenceChecking(presenceCheckDelay, callback);
+ dispatchTagEndpoint(tag, readerParams);
+ } else {
+ if (tag.reconnect()) {
+ if(tag.getConnectedTechnology() == TagTechnology.NFC_F)
+ {
+ presenceCheckDelay = NFC_F_TRANSCEIVE_PRESENCE_CHECK_DELAY;
+ }
+ tag.startPresenceChecking(presenceCheckDelay, callback);
+ dispatchTagEndpoint(tag, readerParams);
+ } else {
+ tag.disconnect();
+ playSound(SOUND_ERROR);
+ }
+ }
+ break;
+
+ case MSG_CARD_EMULATION:
+ if (DBG) Log.d(TAG, "Card Emulation message");
+ /* Tell the host-emu manager an AID has been selected on
+ * a secure element.
+ */
+ if (mCardEmulationManager != null) {
+ mCardEmulationManager.onOffHostAidSelected();
+ }
+ Pair<byte[], Pair> transactionInfo = (Pair<byte[], Pair>) msg.obj;
+ Pair<byte[], Integer> dataSrcInfo = (Pair<byte[], Integer>) transactionInfo.second;
+
+ String gsmaSrc = "";
+ String gsmaDataAID = toHexString(transactionInfo.first, 0, transactionInfo.first.length);
+ {
+ Log.d(TAG, "Event source " + dataSrcInfo.second);
+
+ String evtSrc = "";
+ if(dataSrcInfo.second == UICC_ID_TYPE) {
+ evtSrc = NxpConstants.UICC_ID;
+ gsmaSrc = "SIM1";
+ } else if(dataSrcInfo.second == SMART_MX_ID_TYPE) {
+ evtSrc = NxpConstants.SMART_MX_ID;
+ gsmaSrc = "ESE";
+ }
+ /* Send broadcast ordered */
+ Intent TransactionIntent = new Intent();
+ TransactionIntent.setAction(NxpConstants.ACTION_TRANSACTION_DETECTED);
+ TransactionIntent.putExtra(NxpConstants.EXTRA_AID, transactionInfo.first);
+ TransactionIntent.putExtra(NxpConstants.EXTRA_DATA, dataSrcInfo.first);
+ TransactionIntent.putExtra(NxpConstants.EXTRA_SOURCE, evtSrc);
+
+ if (DBG) {
+ Log.d(TAG, "Start Activity Card Emulation event");
+ }
+ mIsSentUnicastReception = false;
+ mContext.sendBroadcast(TransactionIntent, NfcPermissions.NFC_PERMISSION);
+ }
+ /* Send broadcast */
+ Intent aidIntent = new Intent();
+ aidIntent.setAction(ACTION_AID_SELECTED);
+ aidIntent.putExtra(EXTRA_AID, transactionInfo.first);
+ if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED);
+ sendSeBroadcast(aidIntent);
+
+ /* Send "transaction events" to all authorized/registered components" */
+ Intent evtIntent = new Intent();
+ evtIntent.setAction(NxpConstants.ACTION_MULTI_EVT_TRANSACTION);
+ evtIntent.setData(Uri.parse("nfc://secure:0/"+ gsmaSrc+"/"+ gsmaDataAID));
+ evtIntent.putExtra(NxpConstants.EXTRA_GSMA_AID, transactionInfo.first);
+ evtIntent.putExtra(NxpConstants.EXTRA_GSMA_DATA, dataSrcInfo.first);
+ Log.d(TAG, "Broadcasting " + NxpConstants.ACTION_MULTI_EVT_TRANSACTION);
+ sendMultiEvtBroadcast(evtIntent);
+
+ break;
+
+ case MSG_CONNECTIVITY_EVENT:
+ if (DBG) {
+ Log.d(TAG, "SE EVENT CONNECTIVITY");
+ }
+ Integer evtSrcInfo = (Integer) msg.obj;
+ Log.d(TAG, "Event source " + evtSrcInfo);
+ String evtSrc = "";
+ if(evtSrcInfo == UICC_ID_TYPE) {
+ evtSrc = NxpConstants.UICC_ID;
+ } else if(evtSrcInfo == SMART_MX_ID_TYPE) {
+ evtSrc = NxpConstants.SMART_MX_ID;
+ }
+
+ Intent eventConnectivityIntent = new Intent();
+ eventConnectivityIntent.setAction(NxpConstants.ACTION_CONNECTIVITY_EVENT_DETECTED);
+ eventConnectivityIntent.putExtra(NxpConstants.EXTRA_SOURCE, evtSrc);
+ if (DBG) {
+ Log.d(TAG, "Broadcasting Intent");
+ }
+ mContext.sendBroadcast(eventConnectivityIntent, NfcPermissions.NFC_PERMISSION);
+ break;
+
+ case MSG_EMVCO_MULTI_CARD_DETECTED_EVENT:
+ if (DBG) {
+ Log.d(TAG, "EMVCO MULTI CARD DETECTED EVENT");
+ }
+
+ Intent eventEmvcoMultiCardIntent = new Intent();
+ eventEmvcoMultiCardIntent.setAction(ACTION_EMVCO_MULTIPLE_CARD_DETECTED);
+ if (DBG) {
+ Log.d(TAG, "Broadcasting Intent");
+ }
+ mContext.sendBroadcast(eventEmvcoMultiCardIntent, NFC_PERM);
+ break;
+
+ case MSG_SE_EMV_CARD_REMOVAL:
+ if (DBG) Log.d(TAG, "Card Removal message");
+ /* Send broadcast */
+ Intent cardRemovalIntent = new Intent();
+ cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL);
+ if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL);
+ sendSeBroadcast(cardRemovalIntent);
+ break;
+
+ case MSG_SE_APDU_RECEIVED:
+ if (DBG) Log.d(TAG, "APDU Received message");
+ byte[] apduBytes = (byte[]) msg.obj;
+ /* Send broadcast */
+ Intent apduReceivedIntent = new Intent();
+ apduReceivedIntent.setAction(ACTION_APDU_RECEIVED);
+ if (apduBytes != null && apduBytes.length > 0) {
+ apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes);
+ }
+ if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED);
+ sendSeBroadcast(apduReceivedIntent);
+ break;
+
+ case MSG_SE_MIFARE_ACCESS:
+ if (DBG) Log.d(TAG, "MIFARE access message");
+ /* Send broadcast */
+ byte[] mifareCmd = (byte[]) msg.obj;
+ Intent mifareAccessIntent = new Intent();
+ mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED);
+ if (mifareCmd != null && mifareCmd.length > 1) {
+ int mifareBlock = mifareCmd[1] & 0xff;
+ if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock);
+ mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock);
+ }
+ if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED);
+ sendSeBroadcast(mifareAccessIntent);
+ break;
+
+ case MSG_LLCP_LINK_ACTIVATION:
+ if (mIsDebugBuild) {
+ Intent actIntent = new Intent(ACTION_LLCP_UP);
+ mContext.sendBroadcast(actIntent);
+ }
+ llcpActivated((NfcDepEndpoint) msg.obj);
+ break;
+
+ case MSG_LLCP_LINK_DEACTIVATED:
+ if (mIsDebugBuild) {
+ Intent deactIntent = new Intent(ACTION_LLCP_DOWN);
+ mContext.sendBroadcast(deactIntent);
+ }
+ NfcDepEndpoint device = (NfcDepEndpoint) msg.obj;
+ boolean needsDisconnect = false;
+
+ Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
+ synchronized (NfcService.this) {
+ /* Check if the device has been already unregistered */
+ if (mObjectMap.remove(device.getHandle()) != null) {
+ /* Disconnect if we are initiator */
+ if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
+ if (DBG) Log.d(TAG, "disconnecting from target");
+ needsDisconnect = true;
+ } else {
+ if (DBG) Log.d(TAG, "not disconnecting from initiator");
+ }
+ }
+ }
+ if (needsDisconnect) {
+ device.disconnect(); // restarts polling loop
+ }
+
+ mP2pLinkManager.onLlcpDeactivated();
+ break;
+ case MSG_LLCP_LINK_FIRST_PACKET:
+ mP2pLinkManager.onLlcpFirstPacketReceived();
+ break;
+ case MSG_TARGET_DESELECTED:
+ /* Broadcast Intent Target Deselected */
+ if (DBG) Log.d(TAG, "Target Deselected");
+ Intent intent = new Intent();
+ intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
+ if (DBG) Log.d(TAG, "Broadcasting Intent");
+ mContext.sendOrderedBroadcast(intent, NfcPermissions.NFC_PERMISSION);
+ break;
+
+ case MSG_SE_FIELD_ACTIVATED: {
+ if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
+ Intent eventFieldOnIntent = new Intent();
+ eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
+ sendSeBroadcast(eventFieldOnIntent);
+ break;
+ }
+ case MSG_RESUME_POLLING:
+ mNfcAdapter.resumePolling();
+ break;
+
+ case MSG_SE_FIELD_DEACTIVATED: {
+ if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
+ Intent eventFieldOffIntent = new Intent();
+ eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
+ sendSeBroadcast(eventFieldOffIntent);
+ break;
+ }
+
+ case MSG_SE_LISTEN_ACTIVATED: {
+ if (DBG) Log.d(TAG, "SE LISTEN MODE ACTIVATED");
+ Intent listenModeActivated = new Intent();
+ listenModeActivated.setAction(ACTION_SE_LISTEN_ACTIVATED);
+ sendSeBroadcast(listenModeActivated);
+ break;
+ }
+
+ case MSG_SE_LISTEN_DEACTIVATED: {
+ if (DBG) Log.d(TAG, "SE LISTEN MODE DEACTIVATED");
+ Intent listenModeDeactivated = new Intent();
+ listenModeDeactivated.setAction(ACTION_SE_LISTEN_DEACTIVATED);
+ sendSeBroadcast(listenModeDeactivated);
+ break;
+ }
+
+ case MSG_SWP_READER_REQUESTED:
+
+ /* Send broadcast ordered */
+ Intent SWPReaderRequestedIntent = new Intent();
+ ArrayList<Integer> techList = (ArrayList<Integer>) msg.obj;
+ Integer techs[] = techList.toArray(new Integer[techList.size()]);
+ SWPReaderRequestedIntent
+ .setAction(NxpConstants.ACTION_SWP_READER_REQUESTED);
+ if (DBG) {
+ Log.d(TAG, "SWP READER - Requested");
+ }
+ mContext.sendBroadcast(SWPReaderRequestedIntent);
+ break;
+
+ case MSG_SWP_READER_REQUESTED_FAIL:
+
+ /* Send broadcast ordered */
+ Intent SWPReaderRequestedFailIntent = new Intent();
+ //ArrayList<Integer> techList = (ArrayList<Integer>) msg.obj;
+ //Integer techs[] = techList.toArray(new Integer[techList.size()]);
+ //Intent SWPReaderRequestedFailIntent = new Intent();
+ //Integer FailCause = (Integer) msg.obj;
+
+ //SWPReaderRequestedFailIntent.setAction(NfcAdapter.ACTION_SWP_READER_REQUESTED_FAIL);
+ //SWPReaderRequestedFailIntent.putExtra(NfcAdapter.EXTRA_SWP_READER_REQ_FAIL,FailCause);
+ SWPReaderRequestedFailIntent
+ .setAction(NxpConstants.ACTION_SWP_READER_REQUESTED_FAILED);
+ if (DBG) {
+ Log.d(TAG, "SWP READER - Requested Fail");
+ }
+ mContext.sendBroadcast(SWPReaderRequestedFailIntent);
+ break;
+
+ case MSG_SWP_READER_ACTIVATED:
+
+ /* Send broadcast ordered */
+ Intent SWPReaderActivatedIntent = new Intent();
+
+ SWPReaderActivatedIntent
+ .setAction(NxpConstants.ACTION_SWP_READER_ACTIVATED);
+ if (DBG) {
+ Log.d(TAG, "SWP READER - Activated");
+ }
+ mContext.sendBroadcast(SWPReaderActivatedIntent);
+ break;
+
+ case MSG_ETSI_START_CONFIG:
+ {
+ Log.d(TAG, "NfcServiceHandler - MSG_ETSI_START_CONFIG");
+ ArrayList<Integer> configList = (ArrayList<Integer>) msg.obj;
+ int eeHandle;
+ if(configList.contains(0x402))
+ {
+ eeHandle = 0x402;
+ }
+ else{
+ eeHandle = 0x4C0;
+ }
+ etsiStartConfig(eeHandle);
+ }
+ break;
+
+ case MSG_ETSI_STOP_CONFIG:
+
+ Log.d(TAG, "NfcServiceHandler - MSG_ETSI_STOP_CONFIG");
+
+ etsiStopConfig((int)msg.obj);
+ break;
+
+ case MSG_ETSI_SWP_TIMEOUT:
+
+ Log.d(TAG, "NfcServiceHandler - MSG_ETSI_SWP_TIMEOUT");
+
+ mDeviceHost.setEtsiReaederState(STATE_SE_RDR_MODE_STOP_CONFIG);
+ etsiStopConfig((int)msg.obj);
+
+ break;
+ case MSG_APPLY_SREEN_STATE:
+
+ mScreenState = (int)msg.obj;
+ mDeviceHost.doSetScreenOrPowerState(mScreenState);
+ mRoutingWakeLock.acquire();
+ try {
+ Log.e(TAG, "applyRouting -20");
+ applyRouting(false);
+ } finally {
+ mRoutingWakeLock.release();
+ }
+ break;
+ default:
+ Log.e(TAG, "Unknown message received");
+ break;
+ }
+ }
+
+ private void sendSeBroadcast(Intent intent) {
+ intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ // Resume app switches so the receivers can start activites without delay
+ mNfcDispatcher.resumeAppSwitches();
+ ArrayList<String> matchingPackages = new ArrayList<String>();
+ ArrayList<String> preferredPackages = new ArrayList<String>();
+ if(mInstalledPackages == null) {
+ Log.d(TAG, "No packages to send broadcast.");
+ return;
+ }
+ synchronized(this) {
+ for (PackageInfo pkg : mInstalledPackages) {
+ if (pkg != null && pkg.applicationInfo != null) {
+ if (mNfceeAccessControl.check(pkg.applicationInfo)) {
+ matchingPackages.add(pkg.packageName);
+ if (mCardEmulationManager != null &&
+ mCardEmulationManager.packageHasPreferredService(pkg.packageName)) {
+ preferredPackages.add(pkg.packageName);
+ }
+ }
+ }
+ }
+ if (preferredPackages.size() > 0) {
+ // If there's any packages in here which are preferred, only
+ // send field events to those packages, to prevent other apps
+ // with signatures in nfcee_access.xml from acting upon the events.
+ for (String packageName : preferredPackages){
+ intent.setPackage(packageName);
+ mContext.sendBroadcast(intent);
+ }
+ } else {
+ for (String packageName : matchingPackages){
+ intent.setPackage(packageName);
+ mContext.sendBroadcast(intent);
+ }
+ }
+ }
+ }
+
+ private void sendMultiEvtBroadcast(Intent intent) {
+
+ ArrayList<String> packageList = mNxpNfcController.getEnabledMultiEvtsPackageList();
+ if(packageList.size() == 0) {
+ Log.d(TAG, "No packages to send broadcast.");
+ return;
+ }
+
+ for(int i=0; i<packageList.size(); i++) {
+ Log.d(TAG,"MultiEvt Enabled Application packageName: " + packageList.get(i));
+ intent.setPackage(packageList.get(i));
+ mContext.sendBroadcast(intent, NxpConstants.PERMISSIONS_TRANSACTION_EVENT);
+ }
+ }
+
+ private boolean llcpActivated(NfcDepEndpoint device) {
+ Log.d(TAG, "LLCP Activation message");
+
+ if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
+ if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
+ if (device.connect()) {
+ /* Check LLCP compliance */
+ if (mDeviceHost.doCheckLlcp()) {
+ /* Activate LLCP Link */
+ if (mDeviceHost.doActivateLlcp()) {
+ if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
+ synchronized (NfcService.this) {
+ // Register P2P device
+ mObjectMap.put(device.getHandle(), device);
+ }
+ mP2pLinkManager.onLlcpActivated();
+ return true;
+ } else {
+ /* should not happen */
+ Log.w(TAG, "Initiator LLCP activation failed. Disconnect.");
+ device.disconnect();
+ }
+ } else {
+ if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
+ device.disconnect();
+ }
+ } else {
+ if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted.");
+ /*
+ * The polling loop should have been restarted in failing
+ * doConnect
+ */
+ }
+ } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) {
+ if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
+ /* Check LLCP compliancy */
+ if (mDeviceHost.doCheckLlcp()) {
+ /* Activate LLCP Link */
+ if (mDeviceHost.doActivateLlcp()) {
+ if (DBG) Log.d(TAG, "Target Activate LLCP OK");
+ synchronized (NfcService.this) {
+ // Register P2P device
+ mObjectMap.put(device.getHandle(), device);
+ }
+ mP2pLinkManager.onLlcpActivated();
+ return true;
+ }
+ } else {
+ Log.w(TAG, "checkLlcp failed");
+ }
+ }
+
+ return false;
+ }
+
+ private void dispatchTagEndpoint(TagEndpoint tagEndpoint, ReaderModeParams readerParams) {
+ Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(),
+ tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService);
+ registerTagObject(tagEndpoint);
+ if (readerParams != null) {
+ try {
+ if ((readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) {
+ playSound(SOUND_END);
+ }
+ if (readerParams.callback != null) {
+ readerParams.callback.onTagDiscovered(tag);
+ return;
+ } else {
+ // Follow normal dispatch below
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Reader mode remote has died, falling back.", e);
+ // Intentional fall-through
+ } catch (Exception e) {
+ // Catch any other exception
+ Log.e(TAG, "App exception, not dispatching.", e);
+ return;
+ }
+ }
+ int dispatchResult = mNfcDispatcher.dispatchTag(tag);
+ if (dispatchResult == NfcDispatcher.DISPATCH_FAIL) {
+ unregisterObject(tagEndpoint.getHandle());
+ playSound(SOUND_ERROR);
+ } else if (dispatchResult == NfcDispatcher.DISPATCH_SUCCESS) {
+ playSound(SOUND_END);
+ }
+ }
+ }
+
+ private NfcServiceHandler mHandler = new NfcServiceHandler();
+
+ class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> {
+ @Override
+ protected Void doInBackground(Integer... params) {
+ synchronized (NfcService.this) {
+ if (params == null || params.length != 1) {
+ // force apply current routing
+ Log.e(TAG, "applyRouting -1");
+ applyRouting(true);
+ return null;
+ }
+ mScreenState = params[0].intValue();
+ mDeviceHost.doSetScreenOrPowerState(mScreenState);
+ mRoutingWakeLock.acquire();
+ try {
+ Log.e(TAG, "applyRouting -2");
+ applyRouting(false);
+ } finally {
+ mRoutingWakeLock.release();
+ }
+ return null;
+ }
+ }
+ }
+
+ class TagRemoveTask extends AsyncTask<Integer, Void, Void> {
+ @Override
+ protected Void doInBackground(Integer... params) {
+
+ Intent SWPReaderTagRemoveIntent = new Intent();
+
+ SWPReaderTagRemoveIntent.setAction(NxpConstants.ACTION_SWP_READER_TAG_REMOVE);
+
+ int counter = 0;
+ int discNtfTimeout = params[0].intValue();
+
+ while(ETSI_STOP_CONFIG == true)
+ { /* Send broadcast ordered */
+
+ if(discNtfTimeout == 0)
+ {
+ /*Do nothing*/
+ }
+ else if(counter < discNtfTimeout)
+ {
+ counter++;
+ }
+ else
+ {
+ ETSI_STOP_CONFIG = false;
+ break;
+ }
+ if (DBG) {
+ Log.d(TAG, "SWP READER - Tag Remove");
+ }
+ mContext.sendBroadcast(SWPReaderTagRemoveIntent);
+ try{
+ Thread.sleep(1000);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+ }
+
+
+ private final BroadcastReceiver x509CertificateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ boolean result = intent.getBooleanExtra(NxpConstants.EXTRA_RESULT, false);
+ mNxpNfcController.setResultForCertificates(result);
+ }
+ };
+
+ private final BroadcastReceiver mEnableNfc = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ Intent nfcDialogIntent = new Intent(mContext, EnableNfcDialogActivity.class);
+ nfcDialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivityAsUser(nfcDialogIntent, UserHandle.CURRENT);
+ }
+ };
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(
+ NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
+ // Perform applyRouting() in AsyncTask to serialize blocking calls
+ new ApplyRoutingTask().execute();
+ } else if ((action.equals(Intent.ACTION_SCREEN_ON)
+ || action.equals(Intent.ACTION_SCREEN_OFF)
+ || action.equals(Intent.ACTION_USER_PRESENT)) &&
+ mState == NfcAdapter.STATE_ON) {
+ // Perform applyRouting() in AsyncTask to serialize blocking calls
+ int screenState = ScreenStateHelper.SCREEN_STATE_OFF;
+ if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ if(mScreenState != ScreenStateHelper.SCREEN_STATE_OFF)
+ {
+ screenState = ScreenStateHelper.SCREEN_STATE_OFF;
+ }
+ //mDeviceHost.doSetScreenOrPowerState(ScreenStateHelper.SCREEN_STATE_OFF);
+ } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ screenState = mKeyguard.isKeyguardLocked() ?
+ ScreenStateHelper.SCREEN_STATE_ON_LOCKED : ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
+ if(screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mScreenState == ScreenStateHelper.SCREEN_STATE_OFF) {
+ //mDeviceHost.doSetScreenOrPowerState(ScreenStateHelper.SCREEN_STATE_ON_LOCKED);
+ } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mScreenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
+ return;
+ }
+ } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
+ if (mScreenState != ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED) {
+ screenState = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
+ //mDeviceHost.doSetScreenOrPowerState(ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED);
+ } else {
+ return;
+ }
+ }
+ // TODO mCardEmulationManager.setScreenState(screenState);
+ sendMessage(NfcService.MSG_APPLY_SREEN_STATE, screenState);
+ //new ApplyRoutingTask().execute(Integer.valueOf(screenState));
+ } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
+ boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
+ // Query the airplane mode from Settings.System just to make sure that
+ // some random app is not sending this intent
+ if (isAirplaneModeOn != isAirplaneModeOn()) {
+ return;
+ }
+ if (!mIsAirplaneSensitive) {
+ return;
+ }
+ mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false);
+ mPrefsEditor.apply();
+ if (isAirplaneModeOn) {
+ new EnableDisableTask().execute(TASK_DISABLE);
+ } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
+ new EnableDisableTask().execute(TASK_ENABLE);
+ }
+ } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
+ int screenState = ScreenStateHelper.SCREEN_STATE_OFF;
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ synchronized (this) {
+ mUserId = userId;
+ }
+ mP2pLinkManager.onUserSwitched(getUserId());
+ if (mIsHceCapable) {
+ mCardEmulationManager.onUserSwitched(getUserId());
+ }
+ if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED) {
+ screenState = ScreenStateHelper.SCREEN_STATE_ON_LOCKED;
+ }else {
+ return;
+ }
+ new ApplyRoutingTask().execute(Integer.valueOf(screenState));
+ } else if(action.equals(Intent.ACTION_SHUTDOWN)) {
+ mPowerShutDown = true;
+ Log.d(TAG,"Device is shutting down.");
+ }
+ }
+ };
+
+ private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
+ action.equals(Intent.ACTION_PACKAGE_ADDED) ||
+ action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) ||
+ action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
+ updatePackageCache();
+
+ if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
+ // Clear the NFCEE access cache in case a UID gets recycled
+ mNfceeAccessControl.invalidateCache();
+ }
+ }
+ }
+ };
+
+ final BroadcastReceiver mAlaReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(intent.getAction())) {
+ int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
+ NfcAdapter.STATE_OFF);
+ if (state == NfcAdapter.STATE_ON) {
+ Log.e(TAG, "Loader service update start from NFC_ON Broadcast");
+ NfcAlaService nas = new NfcAlaService();
+ if(mNfcAla.doGetLSConfigVersion() == LOADER_SERVICE_VERSION_21)
+ nas.updateLoaderService();
+ }
+ }
+ }
+ };
+
+ private final BroadcastReceiver mPolicyReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent){
+ String action = intent.getAction();
+ if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
+ .equals(action)) {
+ enforceBeamShareActivityPolicy(context,
+ new UserHandle(getSendingUserId()), mIsNdefPushEnabled);
+ }
+ }
+ };
+
+ /**
+ * Returns true if airplane mode is currently on
+ */
+ boolean isAirplaneModeOn() {
+ return Settings.System.getInt(mContentResolver,
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+ }
+
+ /**
+ * for debugging only - no i18n
+ */
+ static String stateToString(int state) {
+ switch (state) {
+ case NfcAdapter.STATE_OFF:
+ return "off";
+ case NfcAdapter.STATE_TURNING_ON:
+ return "turning on";
+ case NfcAdapter.STATE_ON:
+ return "on";
+ case NfcAdapter.STATE_TURNING_OFF:
+ return "turning off";
+ default:
+ return "<error>";
+ }
+ }
+
+ void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump nfc from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " without permission " + android.Manifest.permission.DUMP);
+ return;
+ }
+
+ synchronized (this) {
+ pw.println("mState=" + stateToString(mState));
+ pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled);
+ pw.println("mScreenState=" + ScreenStateHelper.screenStateToString(mScreenState));
+ pw.println("mNfcPollingEnabled=" + mNfcPollingEnabled);
+ pw.println("mNfceeRouteEnabled=" + mNfceeRouteEnabled);
+ pw.println("mOpenEe=" + mOpenEe);
+ pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive);
+ pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable);
+ pw.println("mLockscreenPollMask=" + mLockscreenPollMask);
+ pw.println(mCurrentDiscoveryParameters);
+ mP2pLinkManager.dump(fd, pw, args);
+ if (mIsHceCapable) {
+ mCardEmulationManager.dump(fd, pw, args);
+ }
+ mNfceeAccessControl.dump(fd, pw, args);
+ mNfcDispatcher.dump(fd, pw, args);
+ pw.println(mDeviceHost.dump());
+
+ }
+ }
+}