/*
* 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.
*/
package com.android.nfc;
import android.app.ActivityManager;
import android.app.Application;
import android.app.KeyguardManager;
import android.app.PendingIntent;
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.PackageInfo;
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.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.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.cardemulation.CardEmulationManager;
import com.android.nfc.dhimpl.NativeNfcManager;
import com.android.nfc.handover.HandoverManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
public class NfcService implements DeviceHostListener {
static final boolean DBG = false;
static final String TAG = "NfcService";
public static final String SERVICE_NAME = "nfc";
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";
static final int MSG_NDEF_TAG = 0;
static final int MSG_LLCP_LINK_ACTIVATION = 1;
static final int MSG_LLCP_LINK_DEACTIVATED = 2;
static final int MSG_MOCK_NDEF = 3;
static final int MSG_LLCP_LINK_FIRST_PACKET = 4;
static final int MSG_ROUTE_AID = 5;
static final int MSG_UNROUTE_AID = 6;
static final int MSG_COMMIT_ROUTING = 7;
static final int MSG_INVOKE_BEAM = 8;
static final int MSG_RF_FIELD_ACTIVATED = 9;
static final int MSG_RF_FIELD_DEACTIVATED = 10;
static final int MSG_RESUME_POLLING = 11;
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;
// 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;
// Time to wait for routing to be applied before watchdog
// goes off
static final int ROUTING_WATCHDOG_MS = 10000;
// Default delay used for presence checks
static final int DEFAULT_PRESENCE_CHECK_DELAY = 125;
// 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;
// RF field events as defined in NFC extras
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";
// 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;
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";
// 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 final ReaderModeDeathRecipient mReaderModeDeathRecipient =
new ReaderModeDeathRecipient();
private final NfcUnlockManager mNfcUnlockManager;
private final NfceeAccessControl mNfceeAccessControl;
List<PackageInfo> mInstalledPackages; // cached version of installed packages
// fields below are used in multiple threads and protected by synchronized(this)
final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
int mScreenState;
boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning
boolean mIsNdefPushEnabled;
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
// fields below are final after onCreate()
Context mContext;
private DeviceHost mDeviceHost;
private SharedPreferences mPrefs;
private SharedPreferences.Editor mPrefsEditor;
private PowerManager.WakeLock mRoutingWakeLock;
int mStartSound;
int mEndSound;
int mErrorSound;
SoundPool mSoundPool; // playback synchronized on this
P2pLinkManager mP2pLinkManager;
TagService mNfcTagService;
NfcAdapterService mNfcAdapter;
boolean mIsAirplaneSensitive;
boolean mIsAirplaneToggleable;
boolean mIsDebugBuild;
boolean mIsHceCapable;
boolean mPollingPaused;
private NfcDispatcher mNfcDispatcher;
private PowerManager mPowerManager;