Home | History | Annotate | Download | only in cardemulation
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.nfc.cardemulation;
     17 
     18 import java.io.FileDescriptor;
     19 import java.io.PrintWriter;
     20 
     21 import com.android.nfc.ForegroundUtils;
     22 
     23 import android.app.ActivityManager;
     24 import android.content.ComponentName;
     25 import android.content.Context;
     26 import android.nfc.cardemulation.NfcFServiceInfo;
     27 import android.os.Handler;
     28 import android.os.Looper;
     29 import android.util.Log;
     30 
     31 public class EnabledNfcFServices implements com.android.nfc.ForegroundUtils.Callback {
     32     static final String TAG = "EnabledNfcFCardEmulationServices";
     33     static final boolean DBG = false;
     34 
     35     final Context mContext;
     36     final RegisteredNfcFServicesCache mNfcFServiceCache;
     37     final RegisteredT3tIdentifiersCache mT3tIdentifiersCache;
     38     final Callback mCallback;
     39     final ForegroundUtils mForegroundUtils = ForegroundUtils.getInstance();
     40     final Handler mHandler = new Handler(Looper.getMainLooper());
     41 
     42     final Object mLock = new Object();
     43     // Variables below synchronized on mLock
     44     ComponentName mForegroundComponent = null; // The computed enabled foreground component
     45     ComponentName mForegroundRequested = null; // The component requested to be enabled by fg app
     46     int mForegroundUid = -1; // The UID of the fg app, or -1 if fg app didn't request
     47 
     48     boolean mComputeFgRequested = false;
     49     boolean mActivated = false;
     50 
     51     public interface Callback {
     52         void onEnabledForegroundNfcFServiceChanged(ComponentName service);
     53     }
     54 
     55     public EnabledNfcFServices(Context context,
     56             RegisteredNfcFServicesCache nfcFServiceCache,
     57             RegisteredT3tIdentifiersCache t3tIdentifiersCache, Callback callback) {
     58         if (DBG) Log.d(TAG, "EnabledNfcFServices");
     59         mContext = context;
     60         mNfcFServiceCache = nfcFServiceCache;
     61         mT3tIdentifiersCache = t3tIdentifiersCache;
     62         mCallback = callback;
     63     }
     64 
     65     void computeEnabledForegroundService() {
     66         if (DBG) Log.d(TAG, "computeEnabledForegroundService");
     67         ComponentName foregroundRequested = null;
     68         boolean changed = false;
     69         synchronized (mLock) {
     70             if (mActivated) {
     71                 Log.d(TAG, "configuration will be postponed until deactivation");
     72                 mComputeFgRequested = true;
     73                 return;
     74             }
     75             mComputeFgRequested = false;
     76             foregroundRequested = mForegroundRequested;
     77             if (mForegroundRequested != null &&
     78                     (mForegroundComponent == null ||
     79                     !mForegroundRequested.equals(mForegroundComponent))) {
     80                 mForegroundComponent = mForegroundRequested;
     81                 changed = true;
     82             } else if (mForegroundRequested == null && mForegroundComponent != null){
     83                 mForegroundComponent = mForegroundRequested;
     84                 changed = true;
     85             }
     86         }
     87         // Notify if anything changed
     88         if (changed) {
     89             mCallback.onEnabledForegroundNfcFServiceChanged(foregroundRequested);
     90         }
     91     }
     92 
     93     public void onServicesUpdated() {
     94         if (DBG) Log.d(TAG, "onServicesUpdated");
     95         // If enabled foreground service is set, remove it
     96         boolean changed = false;
     97         synchronized (mLock) {
     98             if (mForegroundComponent != null) {
     99                 Log.d(TAG, "Removing foreground enabled service because of service update.");
    100                 mForegroundRequested = null;
    101                 mForegroundUid = -1;
    102                 changed = true;
    103             }
    104         }
    105         if (changed) {
    106             computeEnabledForegroundService();
    107         }
    108     }
    109 
    110     public boolean registerEnabledForegroundService(ComponentName service, int callingUid) {
    111         if (DBG) Log.d(TAG, "registerEnabledForegroundService");
    112         boolean success = false;
    113         synchronized (mLock) {
    114             NfcFServiceInfo serviceInfo = mNfcFServiceCache.getService(
    115                     ActivityManager.getCurrentUser(), service);
    116             if (serviceInfo == null) {
    117                 return false;
    118             } else {
    119                 if (serviceInfo.getSystemCode().equalsIgnoreCase("NULL") ||
    120                         serviceInfo.getNfcid2().equalsIgnoreCase("NULL")) {
    121                     return false;
    122                 }
    123             }
    124             if (service.equals(mForegroundRequested)) {
    125                 Log.e(TAG, "The servcie is already requested to the foreground service.");
    126                 return true;
    127             }
    128             if (mForegroundUtils.registerUidToBackgroundCallback(this, callingUid)) {
    129                 mForegroundRequested = service;
    130                 mForegroundUid = callingUid;
    131                 success = true;
    132             } else {
    133                 Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
    134             }
    135         }
    136         if (success) {
    137             computeEnabledForegroundService();
    138         }
    139         return success;
    140     }
    141 
    142     boolean unregisterForegroundService(int uid) {
    143         if (DBG) Log.d(TAG, "unregisterForegroundService");
    144         boolean success = false;
    145         synchronized (mLock) {
    146             if (mForegroundUid == uid) {
    147                 mForegroundRequested = null;
    148                 mForegroundUid = -1;
    149                 success = true;
    150             } // else, other UID in foreground
    151         }
    152         if (success) {
    153             computeEnabledForegroundService();
    154         }
    155         return success;
    156     }
    157 
    158     public boolean unregisteredEnabledForegroundService(int callingUid) {
    159         if (DBG) Log.d(TAG, "unregisterEnabledForegroundService");
    160         // Verify the calling UID is in the foreground
    161         if (mForegroundUtils.isInForeground(callingUid)) {
    162             return unregisterForegroundService(callingUid);
    163         } else {
    164             Log.e(TAG, "Calling UID is not in the foreground, ignorning!");
    165             return false;
    166         }
    167     }
    168 
    169     @Override
    170     public void onUidToBackground(int uid) {
    171         if (DBG) Log.d(TAG, "onUidToBackground");
    172         unregisterForegroundService(uid);
    173     }
    174 
    175     public void onHostEmulationActivated() {
    176         if (DBG) Log.d(TAG, "onHostEmulationActivated");
    177         synchronized (mLock) {
    178             mActivated = true;
    179         }
    180     }
    181 
    182     public void onHostEmulationDeactivated() {
    183         if (DBG) Log.d(TAG, "onHostEmulationDeactivated");
    184         boolean needComputeFg = false;
    185         synchronized (mLock) {
    186             mActivated = false;
    187             if (mComputeFgRequested) {
    188                 needComputeFg = true;
    189             }
    190         }
    191         if (needComputeFg) {
    192             Log.d(TAG, "do postponed configuration");
    193             computeEnabledForegroundService();
    194         }
    195     }
    196 
    197     public void onNfcDisabled() {
    198         synchronized (mLock) {
    199             mForegroundComponent = null;
    200             mForegroundRequested = null;
    201             mActivated = false;
    202             mComputeFgRequested = false;
    203             mForegroundUid = -1;
    204         }
    205     }
    206 
    207     public void onUserSwitched(int userId) {
    208         synchronized (mLock) {
    209             mForegroundComponent = null;
    210             mForegroundRequested = null;
    211             mActivated = false;
    212             mComputeFgRequested = false;
    213             mForegroundUid = -1;
    214         }
    215     }
    216 
    217     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    218     }
    219 }
    220