نمای کلی شبیه‌سازی کارت میزبان‌مبنا

بسیاری از دستگاه‌های مجهز به Android که عملکرد NFC را ارائه می‌دهند، از قبل از شبیه‌سازی کارت NFC پشتیبانی می‌کنند. در بیشتر موارد، کارت توسط تراشه جداگانه‌ای در دستگاه شبیه‌سازی می‌شود که عنصر امن نام دارد. بسیاری از سیم‌کارت‌هایی که شرکت‌های مخابراتی بی‌سیم ارائه می‌دهند نیز حاوی عنصر امن هستند.

Android نسخه ۴.۴ و بالاتر روش دیگری برای شبیه‌سازی کارت ارائه می‌دهد که شامل عنصر امن نیست و شبیه‌سازی کارت مبتنی بر میزبان نامیده می‌شود. این به هر برنامه Android اجازه می‌دهد تا کارتی را شبیه‌سازی کند و مستقیماً با NFC خواننده صحبت کند. این موضوع نحوه عملکرد شبیه‌سازی کارت مبتنی بر میزبان (HCE) را در Android و نحوه توسعه برنامه‌ای که کارت NFC را بااستفاده از این تکنیک شبیه‌سازی می‌کند شرح می‌دهد.

شبیه‌سازی کارت با عنصر امنیتی

When NFC card emulation is provided using a secure element, the card to be emulated is provisioned into the secure element on the device through an Android application. سپس، وقتی کاربر دستگاه را روی پایانه NFC نگه می‌دارد، کنترل‌کننده NFC در دستگاه همه داده‌ها را از کارت‌خوان مستقیماً به عنصر امن هدایت می‌کند. شکل ۱ این مفهوم را نشان می‌دهد:

نمودار با NFCخوان که ازطریق کنترل‌کننده NFC اطلاعات را از عنصر امن بازیابی می‌کند
شکل ۱. شبیه‌سازی کارت NFC با عنصر امنیتی.

خود عنصر امن ارتباط با پایانه NFC را انجام می‌دهد و هیچ برنامه Android در تراکنش دخیل نیست. پس‌از تکمیل تراکنش، برنامه Android می‌تواند مستقیماً از عنصر امن برای وضعیت تراکنش پرس‌وجو کند و به کاربر اطلاع دهد.

شبیه‌سازی کارت میزبان‌مبنا

وقتی کارت NFC بااستفاده از شبیه‌سازی کارت مبتنی بر میزبان شبیه‌سازی می‌شود، داده‌ها به‌جای هدایت به عنصر امن، مستقیماً به CPU میزبان هدایت می‌شوند. شکل ۲ نحوه عملکرد شبیه‌سازی کارت میزبان‌پایه را نشان می‌دهد:

نمودار با NFCخوان که ازطریق کنترل‌کننده NFC اطلاعات را از CPU بازیابی می‌کند
شکل ۲. شبیه‌سازی کارت NFC بدون عنصر امن.

کارت‌ها و پروتکل‌های NFC پشتیبانی‌شده

نموداری که پشته پروتکل HCE را نشان می‌دهد
شکل ۳. پشته پروتکل HCE در Android.

استانداردهای NFC از پروتکل‌های مختلفی پشتیبانی می‌کنند و انواع مختلفی از کارت‌ها وجود دارد که می‌توانید شبیه‌سازی کنید.

Android نسخه ۴.۴ و بالاتر از چندین پروتکل که امروزه در بازار رایج است پشتیبانی می‌کند. بسیاری از کارت‌های غیرلمسی موجود، مثل کارت‌های پرداخت غیرلمسی، ازقبل براساس این پروتکل‌ها هستند. این پروتکل‌ها همچنین توسط بسیاری از NFCخوان‌های موجود در بازار امروز پشتیبانی می‌شوند، ازجمله دستگاه‌های Android NFC که خودشان به‌عنوان خواننده عمل می‌کنند (به کلاس IsoDep مراجعه کنید). این به شما امکان می‌دهد تا یک راهکار NFC سرتاسر را حول HCE فقط بااستفاده از دستگاه‌های مجهز به Android بسازید و مستقر کنید.

به‌طور خاص، Android نسخه ۴.۴ و بالاتر از شبیه‌سازی کارت‌هایی پشتیبانی می‌کند که براساس مشخصات NFC-Forum ISO-DEP (براساس ISO/IEC 14443-4) هستند و «واحدهای داده پروتکل برنامه» (APDU) را طبق تعریف در مشخصات ISO/IEC 7816-4 پردازش می‌کنند. ‫Android شبیه‌سازی ISO-DEP را فقط در بالای فناوری Nfc-A (ISO/IEC 14443-3 Type A) الزامی می‌کند. پشتیبانی از فناوری Nfc-B (ISO/IEC 14443-4 Type B) اختیاری است. شکل ۳ لایه‌بندی همه این مشخصات را نشان می‌دهد.

سرویس‌های شبیه‌سازی کارت میزبان

معماری HCE در Android براساس مؤلفه‌های Android Service (معروف به سرویس‌های HCE) است. یکی از مزایای کلیدی سرویس این است که می‌تواند بدون هیچ میانای کاربری در پس‌زمینه اجرا شود. این ویژگی برای بسیاری از برنامه‌های HCE، مانند کارت‌های وفاداری یا حمل‌ونقل عمومی، که کاربر نباید برای استفاده از آن‌ها برنامه‌ای را راه‌اندازی کند، مناسب است. درعوض، با زدن دستگاه به NFCخوان، سرویس صحیح شروع می‌شود (اگر ازقبل درحال اجرا نباشد) و تراکنش در پس‌زمینه اجرا می‌شود. البته، درصورت لزوم می‌توانید واسط کاربر دیگری (مانند اعلان‌های کاربر) را از سرویس خود راه‌اندازی کنید.

انتخاب سرویس

وقتی کاربر دستگاهی را به کارت‌خوان NFC نزدیک می‌کند، سیستم Android باید بداند کارت‌خوان NFC می‌خواهد با کدام سرویس HCE ارتباط برقرار کند. مشخصات ISO/IEC 7816-4 روشی را برای انتخاب برنامه‌ها تعریف می‌کند که حول «شناسه برنامه» (AID) متمرکز است. شناسه برنامه از حداکثر ۱۶ بایت تشکیل شده است. اگر کارت‌ها را برای زیرساخت کارت‌خوان NFC موجود شبیه‌سازی می‌کنید، شناسه‌های برنامه‌ای که آن کارت‌خوان‌ها به‌دنبالشان هستند معمولاً شناخته‌شده و به‌طور عمومی ثبت‌شده هستند (برای مثال، شناسه‌های برنامه شبکه‌های پرداخت مانند Visa و MasterCard).

اگر می‌خواهید زیرساخت خواننده جدیدی برای برنامه خودتان مستقر کنید، باید AIDهای خودتان را ثبت کنید. رویه ثبت برای AID در مشخصات ISO/IEC 7816-5 تعریف شده است. توصیه می‌کنیم AID را طبق 7816-5 ثبت کنید اگر برنامه HCE را برای Android مستقر می‌کنید، زیرا از تداخل با برنامه‌های دیگر جلوگیری می‌کند.

گروه‌های AID

In some cases, an HCE service may need to register multiple AIDs and be set as the default handler for all of the AIDs in order to implement a certain application. انتقال برخی‌از شناسه‌های AID در گروه به سرویسی دیگر پشتیبانی نمی‌شود.

فهرستی از شناسه‌های AID که باهم نگهداری می‌شوند گروه AID نامیده می‌شود. برای همه شناسه‌های AID در یک گروه AID،‏ Android یکی از موارد زیر را تضمین می‌کند:

  • همه شناسه‌های برنامه در گروه به این سرویس «شبیه‌سازی کارت میزبان» هدایت می‌شوند.
  • هیچ شناسه برنامه‌ای در گروه به این سرویس HCE هدایت نمی‌شود (برای مثال، چون کاربر سرویس دیگری را ترجیح داده است که یک یا چند شناسه برنامه را در گروه شما نیز درخواست کرده است).

به‌عبارت دیگر، حالت بینابینی وجود ندارد که در آن برخی‌از شناسه‌های AID در گروه بتوانند به یک سرویس HCE و برخی دیگر به سرویس دیگری هدایت شوند.

گروه‌ها و دسته‌های AID

می‌توانید هر گروه AID را با یک دسته مرتبط کنید. این کار به Android امکان می‌دهد سرویس‌های HCE را براساس دسته گروه‌بندی کند و این به‌نوبه خود به کاربر امکان می‌دهد پیش‌فرض‌ها را در سطح دسته به‌جای سطح AID تنظیم کند. از ذکر کردن AID در بخش‌های سَمت کاربر برنامه‌تان خودداری کنید، زیرا برای کاربر معمولی معنایی ندارد.

Android نسخه ۴.۴ و بالاتر از دو دسته پشتیبانی می‌کند:

  • CATEGORY_PAYMENT (برنامه‌های پرداخت استاندارد صنعتی را پوشش می‌دهد)
  • CATEGORY_OTHER (برای همه برنامه‌های HCE دیگر)
گروه‌های AID در این دسته می‌توانند همیشه فعال باشند و درصورت لزوم، می‌توانند درطول انتخاب AID توسط خوانندگان NFC اولویت داشته باشند.

برنامه‌هایی که AID را تحت CATEGORY_PAYMENT ثبت می‌کنند فقط درصورتی می‌توانند تراکنش را پردازش کنند که:

  • کاربر برنامه را به‌عنوان برنامه پرداخت پیش‌فرض تنظیم کند (دارنده نقش «کیف پول» در دستگاه‌های Android 15+)، یا
  • برنامه در پیش‌نما است و setPreferredService را فراخوانی می‌کند.

پیاده‌سازی سرویس HCE

برای شبیه‌سازی کارت NFC بااستفاده از شبیه‌سازی کارت مبتنی بر میزبان، باید مؤلفه Service ایجاد کنید که تراکنش‌های NFC را مدیریت می‌کند.

بررسی پشتیبانی از HCE

برنامه شما می‌تواند با بررسی ویژگی FEATURE_NFC_HOST_CARD_EMULATION بررسی کند که آیا دستگاه از HCE پشتیبانی می‌کند یا نه. از برچسب <uses-feature> در مانیفست برنامه‌تان استفاده کنید تا اعلام کنید برنامه‌تان از ویژگی HCE استفاده می‌کند و اینکه آیا این ویژگی برای عملکرد برنامه ضروری است یا نه.

پیاده‌سازی سرویس

Android نسخه ۴.۴ و بالاتر کلاس راحتی Service را ارائه می‌دهد که می‌توانید از آن به‌عنوان پایه‌ای برای پیاده‌سازی سرویس HCE استفاده کنید: کلاس HostApduService.

اولین مرحله گسترش دادن HostApduService است، همان‌طور که در نمونه کد زیر نشان داده شده است:

کاتلین

class MyHostApduService : HostApduService() {

    override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray {
       ...
    }

    override fun onDeactivated(reason: Int) {
       ...
    }
}

جاوا

public class MyHostApduService extends HostApduService {
    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
       ...
    }
    @Override
    public void onDeactivated(int reason) {
       ...
    }
}

HostApduService دو روش انتزاعی را اعلام می‌کند که باید آن‌ها را لغو و پیاده‌سازی کنید. یکی از آن‌ها، processCommandApdu()، هرگاه NFC reader یک «واحد داده پروتکل برنامه» (APDU) به سرویس شما ارسال کند، فراخوانده می‌شود. APDU در مشخصات ISO/IEC 7816-4 تعریف شده است. APDUها بسته‌های سطح برنامه هستند که بین NFCخوان و سرویس HCE شما ردوبدل می‌شوند. آن پروتکل سطح برنامه نیمه‌دوطرفه است: NFC reader یک APDU فرمان برای شما ارسال می‌کند و منتظر می‌ماند تا شما در پاسخ یک APDU پاسخ ارسال کنید.

همان‌طور که قبلاً ذکر شد، Android از AID برای تعیین اینکه کارت‌خوان می‌خواهد با کدام سرویس HCE ارتباط برقرار کند استفاده می‌کند. معمولاً اولین APDU که یک NFCخوان به دستگاه شما ارسال می‌کند، یک APDU SELECT AID است؛ این APDU حاوی AID است که خواننده می‌خواهد با آن ارتباط برقرار کند. ‫Android آن AID را از APDU استخراج می‌کند، آن را به یک سرویس HCE تبدیل می‌کند، و سپس آن APDU را به سرویس تبدیل‌شده بازارسال می‌کند.

می‌توانید با برگرداندن بایت‌های APDU پاسخ از processCommandApdu()، APDU پاسخ ارسال کنید. توجه داشته باشید که این روش در رشته اصلی برنامه شما فراخوانی می‌شود که نباید آن را مسدود کنید. اگر نمی‌توانید APDU پاسخ را فوراً محاسبه و برگردانید، null برگردانید. سپس می‌توانید کار لازم را در رشته دیگری انجام دهید و از روش sendResponseApdu() تعریف‌شده در کلاس HostApduService برای ارسال پاسخ پس‌از اتمام کار استفاده کنید.

‫Android به بازارسال APDUهای جدید از کارت‌خوان به سرویس شما ادامه می‌دهد تا زمانی که یکی از موارد زیر اتفاق بیفتد:

  • کارت‌خوان NFC یک SELECT AID APDU دیگر ارسال می‌کند که سیستم‌عامل آن را به سرویس دیگری ارجاع می‌دهد.
  • پیوند NFC بین کارت‌خوان NFC و دستگاهتان قطع شده است.

در هر دو مورد، پیاده‌سازی onDeactivated() کلاس شما با آرگومانی فراخوانی می‌شود که نشان می‌دهد کدام‌یک از این دو اتفاق افتاده است.

اگر با زیرساخت خواننده موجود کار می‌کنید، باید پروتکل سطح برنامه موجود را که خوانندگان در سرویس HCE شما انتظار دارند پیاده‌سازی کنید.

اگر زیرساخت کارت‌خوان جدیدی را مستقر می‌کنید که خودتان هم آن را کنترل می‌کنید، می‌توانید پروتکل و توالی APDU خودتان را تعریف کنید. سعی کنید تعداد APDU-ها و اندازه داده‌های مبادله‌شده را محدود کنید: این کار باعث می‌شود کاربران شما فقط برای مدت کوتاهی دستگاه خود را روی NFCخوان نگه دارند. حد بالای منطقی حدود ۱ کیلوبایت داده است که معمولاً می‌تواند ظرف ۳۰۰ میلی‌ثانیه مبادله شود.

اظهارنامه مانیفست سرویس و ثبت شناسه برنامه

باید سرویس خود را طبق معمول در مانیفست اعلام کنید، اما باید چند قطعه اضافی نیز به اعلامیه سرویس اضافه کنید:

  1. برای اینکه به پلاتفرم بگویید این سرویس HCE است که میانای HostApduService را پیاده‌سازی می‌کند، فیلتر قصدی برای کنش SERVICE_INTERFACE به اعلامیه سرویس خود اضافه کنید.

  2. برای اینکه به پلاتفرم بگویید کدام گروه‌های AID توسط این سرویس درخواست شده‌اند، یک برچسب SERVICE_META_DATA <meta-data> در اعلامیه سرویس اضافه کنید که به یک منبع XML با اطلاعات اضافی درباره سرویس HCE اشاره می‌کند.

  3. مشخصه android:exported را روی true تنظیم کنید و در اظهارنامه سرویس خود، اجازه android.permission.BIND_NFC_SERVICE را الزامی کنید. مورد اول تضمین می‌کند که سرویس می‌تواند توسط برنامه‌های خارجی محدود شود. سپس مورد دوم اعمال می‌کند که فقط برنامه‌های خارجی که دارای اجازه android.permission.BIND_NFC_SERVICE هستند می‌توانند به سرویس شما متصل شوند. ازآنجایی‌که android.permission.BIND_NFC_SERVICE یک اجازه سیستم است، این به‌طور مؤثر اعمال می‌کند که فقط سیستم‌عامل Android می‌تواند به سرویس شما متصل شود.

در زیر نمونه‌ای از اظهارنامه مانیفست HostApduService آمده است:

<service android:name=".MyHostApduService" android:exported="true"
         android:permission="android.permission.BIND_NFC_SERVICE">
    <intent-filter>
        <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
    </intent-filter>
    <meta-data android:name="android.nfc.cardemulation.host_apdu_service"
               android:resource="@xml/apduservice"/>
</service>

این برچسب فراداده به فایل apduservice.xml اشاره می‌کند. در زیر نمونه‌ای از چنین فایلی با یک تعریف گروه AID حاوی دو AID اختصاصی آورده شده است:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
           android:description="@string/servicedesc"
           android:requireDeviceUnlock="false">
    <aid-group android:description="@string/aiddescription"
               android:category="other">
        <aid-filter android:name="F0010203040506"/>
        <aid-filter android:name="F0394148148100"/>
    </aid-group>
</host-apdu-service>

برچسب <host-apdu-service> باید حاوی مشخصه <android:description> باشد که حاوی شرح کاربرپسندی از سرویس باشد که بتوانید در میانای کاربری برنامه نشان دهید. می‌توانید از مشخصه requireDeviceUnlock استفاده کنید تا مشخص کنید که دستگاه قبل‌از اینکه این سرویس را برای رسیدگی به APDU فراخوانی کنید باز شده است.

<host-apdu-service> باید حاوی یک یا چند برچسب <aid-group> باشد. هر برچسب <aid-group> باید موارد زیر را انجام دهد:

  • دارای مشخصه android:description باشد که حاوی شرحی کاربرپسند از گروه AID باشد و برای نمایش در واسط کاربر مناسب باشد.
  • مشخصه android:category آن باید طوری تنظیم شود که دسته‌ای را که گروه AID به آن تعلق دارد نشان دهد، مانند ثابت‌های رشته‌ای تعریف‌شده توسط CATEGORY_PAYMENT یا CATEGORY_OTHER.
  • حاوی یک یا چند برچسب <aid-filter> باشد که هرکدام حاوی یک AID باشد. ‫AID را در قالب شانزده‌شانزدهی مشخص کنید و مطمئن شوید تعداد نویسه‌های آن زوج باشد.

برنامه شما همچنین باید اجازه NFC را داشته باشد تا بتواند به‌عنوان سرویس HCE ثبت شود.

حل تعارض AID

ممکن است چند مؤلفه HostApduService در یک دستگاه نصب شده باشد، و بیش‌از یک سرویس می‌تواند یک AID را ثبت کند. Android بااستفاده از مراحل زیر تعیین می‌کند کدام سرویس فراخوانده شود:

  1. اگر برنامه کیف پول پیش‌فرض انتخاب‌شده کاربر شناسه برنامه را ثبت کرده باشد، آن برنامه فراخوانده می‌شود.
  2. اگر برنامه کیف پول پیش‌فرض شناسه برنامه را ثبت نکرده باشد، سرویسی که شناسه برنامه را ثبت کرده است فراخوانده می‌شود.
  3. اگر بیش‌از یک سرویس شناسه برنامه را ثبت کرده باشد، Android از کاربر می‌پرسد کدام سرویس فراخوانده شود.

اولویت سرویس پیش‌زمینه‌ای

برنامه‌هایی که در پیش‌نما هستند می‌توانند setPreferredService را فراخوانی کنند تا مشخص کنند کدام سرویس شبیه‌سازی کارت باید ترجیح داده شود، درحالی‌که فعالیت خاصی در پیش‌نما است. این اولویت برنامه پیش‌زمینه، حل تعارض AID را لغو می‌کند. این روش زمانی توصیه می‌شود که برنامه پیش‌بینی می‌کند کاربر ممکن است از شبیه‌سازی کارت NFC استفاده کند.

‫Android 13 و بالاتر

برای اینکه با فهرست انتخاب پرداخت پیش‌فرض در واسط کاربر «تنظیمات» بهتر مطابقت داشته باشد، الزام برنما را به نماد مربع تغییر دهید. در حالت ایده‌آل، باید با طراحی نماد راه‌انداز برنامه یکسان باشد. این اصلاح باعث ایجاد هماهنگی بیشتر و ظاهری تمیزتر می‌شود.

Android 12 و نسخه‌های پایین‌تر

اندازه برنمای سرویس را روی ۲۶۰x۹۶ dp تنظیم کنید، سپس اندازه برنمای سرویس را در فایل XML فراداده با افزودن مشخصه android:apduServiceBanner به برچسب <host-apdu-service> که به منبع ترسیم‌شدنی اشاره می‌کند تنظیم کنید. در زیر نمونه‌ای آورده شده است:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:description="@string/servicedesc"
        android:requireDeviceUnlock="false"
        android:apduServiceBanner="@drawable/my_banner">
    <aid-group android:description="@string/aiddescription"
               android:category="payment">
        <aid-filter android:name="F0010203040506"/>
        <aid-filter android:name="F0394148148100"/>
    </aid-group>
</host-apdu-service>

برنامه‌های کیف پول

Android نسخه ۱۵ و بالاتر شامل نقش برنامه کیف پول پیش‌فرض است که کاربر می‌تواند با رفتن به تنظیمات > برنامه‌ها > برنامه‌های پیش‌فرض آن را انتخاب کند. این گزینه برنامه کیف پول پیش‌فرض را برای فراخوانی هنگام تک‌ضرب زدن روی پایانه پرداخت تعریف می‌کند. Android سرویس‌های HCE را که گروه AID با دسته پرداخت را به‌عنوان برنامه‌های کیف پول اعلام کرده‌اند درنظر می‌گیرد.

بررسی کنید برنامه‌تان برنامه کیف پول پیش‌فرض باشد

برنامه‌ها می‌توانند با ارسال RoleManager.ROLE_WALLET به RoleManager.isRoleHeld() بررسی کنند که آیا برنامه کیف پول پیش‌فرض هستند یا نه.

اگر برنامه‌تان پیش‌فرض نیست، می‌توانید با ارسال RoleManager.ROLE_WALLET به RoleManager.createRequestRoleIntent()، نقش کیف پول پیش‌فرض را درخواست کنید.

دارایی‌های لازم برای برنامه‌های کیف پول

برای ارائه تجربه کاربری جذاب‌تر ازنظر بصری، برنامه‌های کیف پول HCE باید برنمای سرویس ارائه دهند.

حالت مشاهده

Android 15 ویژگی حالت مشاهده را معرفی می‌کند. وقتی «حالت مشاهده» فعال باشد، دستگاه می‌تواند حلقه‌های نظرسنجی NFC را مشاهده کند و اعلان‌های مربوط به آن‌ها را به مؤلفه‌های مناسب HostApduService ارسال کند تا بتوانند برای تعامل با پایانه NFC موردنظر آماده شوند. HostApduService می‌تواند با ارسال true به setObserveModeEnabled()، دستگاه را در «حالت مشاهده» قرار دهد. این کار به پشته NFC دستور می‌دهد که تراکنش‌های NFC را مجاز نکند و درعوض به‌طور غیرفعال حلقه‌های نظرسنجی را مشاهده کند.

فیلترهای حلقه نظرسنجی

می‌توانید فیلترهای حلقه نظرسنجی را برای HostApduService بااستفاده از یکی از روش‌های زیر ثبت کنید:

وقتی فیلتر حلقه نظرسنجی با قاب‌های نظرسنجی غیراستاندارد مطابقت داشته باشد، پشته NFC آن قاب‌های نظرسنجی را با فراخوانی روش processPollingFrames() HostApduService مربوطه به آن هدایت می‌کند. این کار به سرویس اجازه می‌دهد تا هرگونه اقدام لازم را برای اطمینان از اینکه کاربر آماده انجام تراکنش است و قصد انجام آن را دارد انجام دهد—برای مثال، اصالت‌سنجی کاربر. اگر یک قرائت‌گر NFC فقط از فریم‌های استاندارد در حلقه نظرسنجی خود استفاده می‌کند، پشته NFC آن فریم‌های نظرسنجی را به سرویس پیش‌زمینه ترجیحی هدایت می‌کند اگر آن سرویس در پیش‌زمینه باشد یا به دارنده نقش کیف پول پیش‌فرض در غیر این صورت.

اعلان‌های قاب نظرسنجی همچنین شامل اندازه‌گیری قدرت میدان مختص فروشنده است که می‌توانید با فراخوانی getVendorSpecificGain() آن را بازیابی کنید. فروشندگان می‌توانند اندازه‌گیری‌ها را بااستفاده از مقیاس خودشان ارائه دهند، به‌شرطی که در یک بایت جا شود.

پاسخ دادن به حلقه‌های نظرسنجی و انتقال از «حالت مشاهده»

وقتی سرویس برای تراکنش آماده شد، می‌تواند با ارسال false به setObserveModeEnabled() از «حالت مشاهده» خارج شود. سپس پشته NFC اجازه می‌دهد تراکنش‌ها ادامه یابد.

مؤلفه‌های HostApduService می‌توانند نشان دهند که «حالت مشاهده» باید هروقت که سرویس پرداخت ترجیحی هستند فعال شود. این کار با تنظیم کردن shouldDefaultToObserveMode روی true در مانیفست یا با فراخوانی CardEmulation.setShouldDefaultToObserveModeForService() انجام می‌شود.

HostApduService و OffHostApduService مؤلفه‌ها همچنین می‌توانند نشان دهند که فیلترهای حلقه نظرسنجی که با قاب‌های حلقه نظرسنجی دریافتی مطابقت دارند باید به‌طور خودکار «حالت مشاهده» را غیرفعال کنند و با تنظیم autoTransact به true در اعلامیه PollingLoopFilter در مانیفست، اجازه دهند تراکنش‌ها ادامه یابند.

اولویت سرویس پیش‌زمینه‌ای

برنامه‌هایی که در پیش‌نما هستند می‌توانند setPreferredService را فراخوانی کنند تا مشخص کنند کدام سرویس شبیه‌سازی کارت باید ترجیح داده شود، درحالی‌که فعالیت خاصی در پیش‌نما است. این اولویت برنامه پیش‌زمینه، وضعیت «حالت مشاهده» دستگاه را که با مقدار shouldDefaultToObserveMode برای سرویس مشخصی مطابقت دارد لغو می‌کند. این اولویت را می‌توان به یکی از روش‌های زیر تنظیم کرد:

رفتار خاموش بودن صفحه و صفحه قفل

رفتار سرویس‌های HCE براساس نسخه Android درحال اجرا در دستگاه متفاوت است.

‫Android 15 و بالاتر

اگر برنامه کیف پول پیش‌فرض «حالت مشاهده» را در دستگاهی که از آن پشتیبانی می‌کند روشن کند، آن برنامه رفتار باز کردن قفل و خاموش شدن صفحه‌نمایش را لغو می‌کند، زیرا کنترل می‌کند که تراکنش چه زمانی می‌تواند ادامه یابد. اگر «حالت مشاهده» الگوی حلقه نظرسنجی قابل‌شناسایی را تشخیص ندهد، برخی‌از برنامه‌های کیف پول ممکن است قبل‌از انجام تراکنش نیاز به باز کردن قفل دستگاه داشته باشند.

توسعه‌دهندگان تشویق می‌شوند با دستگاه‌های خواننده خود کار کنند تا الگوهای حلقه نظرسنجی قابل‌شناسایی را منتشر کنند و برای مدیریت آن الگوها از برنامه خود ثبت‌نام کنند.

‫Android 12 و بالاتر

در برنامه‌هایی که Android 12 (سطح میانای برنامه‌سازی کاربردی ۳۱) و بالاتر را هدف قرار می‌دهند، می‌توانید پرداخت‌های NFC را بدون روشن بودن صفحه‌نمایش دستگاه با تنظیم کردن requireDeviceScreenOn روی false فعال کنید.

‫Android 10 و بالاتر

دستگاه‌های دارای Android نسخه ۱۰ (سطح میانای برنامه‌سازی کاربردی ۲۹) یا بالاتر از NFC ایمن پشتیبانی می‌کنند. وقتی NFC امن روشن است، همه شبیه‌سازهای کارت (برنامه‌های میزبان و برنامه‌های غیرمیزبان) درصورت خاموش بودن صفحه‌نمایش دستگاه دردسترس نیستند. وقتی NFC امن خاموش است، برنامه‌های غیرمیزبان درصورت خاموش بودن صفحه‌نمایش دستگاه دردسترس هستند. بااستفاده از isSecureNfcSupported() می‌توانید پشتیبانی از NFC امن را بررسی کنید.

در دستگاه‌های دارای Android نسخه ۱۰ و بالاتر، همان عملکرد تنظیم android:requireDeviceUnlock روی true مانند دستگاه‌های دارای Android نسخه ۹ و پایین‌تر اعمال می‌شود، اما فقط زمانی که «NFC امن» خاموش باشد. یعنی اگر «NFC امن» روشن باشد، سرویس‌های HCE نمی‌توانند از صفحه قفل صرف‌نظر از تنظیم android:requireDeviceUnlock عمل کنند.

‫Android 9 و نسخه‌های پایین‌تر

در دستگاه‌هایی که Android 9 (سطح API‏ ۲۸) و پایین‌تر را اجرا می‌کنند، وقتی صفحه‌نمایش دستگاه خاموش است، کنترل‌کننده NFC و پردازنده برنامه کاملاً خاموش می‌شوند. بنابراین، وقتی صفحه‌نمایش خاموش است، سرویس‌های HCE کار نمی‌کنند.

همچنین در Android نسخه ۹ و پایین‌تر، سرویس‌های HCE می‌توانند از صفحه قفل عمل کنند. بااین‌حال، این مورد توسط مشخصه android:requireDeviceUnlock در برچسب <host-apdu-service> سرویس HCE شما کنترل می‌شود. به‌طور پیش‌فرض، باز کردن قفل دستگاه الزامی نیست و سرویس شما حتی اگر دستگاه قفل باشد فراخوانده می‌شود.

اگر مشخصه android:requireDeviceUnlock را برای سرویس HCE خود روی true تنظیم کنید، Android در شرایط زیر از کاربر می‌خواهد قفل دستگاه را باز کند:

  • کاربر روی پایانه NFC تک‌ضرب می‌زند.
  • کارت‌خوان NFC شناسه برنامه‌ای را انتخاب کند که به سرویس شما ارجاع داده می‌شود.

پس‌از باز کردن قفل، Android کادر گفتگویی نشان می‌دهد که از کاربر می‌خواهد برای تکمیل تراکنش دوباره تک‌ضرب بزند. این کار ضروری است زیرا ممکن است کاربر برای باز کردن قفل دستگاه، آن را از پایانه NFC دور کرده باشد.

هم‌زیستی با کارت‌های دارای عنصر امنیتی

این بخش برای توسعه‌دهندگانی که برنامه‌ای را مستقر کرده‌اند که برای شبیه‌سازی کارت به عنصر امنیتی متکی است، جالب است. پیاده‌سازی HCE در Android طوری طراحی شده است که به‌طور موازی با دیگر روش‌های پیاده‌سازی شبیه‌سازی کارت، ازجمله استفاده از عناصر امن، کار کند.

این همزیستی براساس اصلی به‌نام مسیریابی AID است. کنترل‌کننده NFC یک جدول مسیریابی را نگه می‌دارد که شامل یک فهرست (محدود) از قوانین مسیریابی است. هر قانون مسیریابی حاوی یک AID و یک مقصد است. مقصد می‌تواند واحد پردازش مرکزی میزبان باشد که برنامه‌های Android در آن اجرا می‌شوند، یا عنصر ایمن متصل‌شده.

وقتی NFC reader یک APDU با SELECT AID ارسال می‌کند، کنترل‌کننده NFC آن را تجزیه می‌کند و بررسی می‌کند که آیا AIDها با هر AID در جدول مسیریابی آن مطابقت دارند یا نه. اگر مطابقت داشته باشد، آن APDU و همه APDUهای پس‌از آن به مقصد مرتبط با AID ارسال می‌شوند تا زمانی که APDU SELECT AID دیگری دریافت شود یا پیوند NFC قطع شود.

شکل ۴ این معماری را نشان می‌دهد:

نمودار با کارت‌خوان NFC که هم با عنصر امن و هم با واحد پردازش مرکزی ارتباط برقرار می‌کند
شکل ۴. Android با هر دو عنصر امنیتی و شبیه‌سازی کارت میزبان کار می‌کند.

کنترل‌کننده NFC معمولاً حاوی یک مسیر پیش‌فرض برای APDU نیز هست. وقتی AID در جدول رهیابی پیدا نشود، از مسیر پیش‌فرض استفاده می‌شود. اگرچه این تنظیم ممکن است از دستگاهی به دستگاه دیگر متفاوت باشد، دستگاه‌های Android ملزم هستند اطمینان حاصل کنند که شناسه‌های برنامه‌ای که توسط برنامه شما ثبت می‌شوند به‌درستی به میزبان هدایت می‌شوند.

برنامه‌های Android که سرویس HCE را پیاده‌سازی می‌کنند یا از عنصر امن استفاده می‌کنند نیازی نیست نگران پیکربندی جدول مسیریابی باشند؛ این کار به‌طور خودکار توسط Android انجام می‌شود. Android فقط باید بداند کدام AIDها را می‌توان با سرویس‌های HCE و کدام‌یک را با عنصر امن مدیریت کرد. جدول مسیریابی به‌طور خودکار براساس سرویس‌های نصب‌شده و سرویس‌هایی که کاربر به‌عنوان سرویس ترجیحی پیکربندی کرده است پیکربندی می‌شود.

بخش زیر توضیح می‌دهد که چگونه AID را برای برنامه‌هایی که از عنصر امن برای شبیه‌سازی کارت استفاده می‌کنند اعلام کنید.

ثبت شناسه برنامه عنصر امن

برنامه‌هایی که از عنصر امن برای شبیه‌سازی کارت استفاده می‌کنند می‌توانند سرویس غیرمیزبان را در مانیفست خود اعلام کنند. اعلام چنین سرویسی تقریباً با اعلام سرویس HCE یکسان است. استثناها به‌شرح زیر است:

  • کنش استفاده‌شده در فیلتر قصد باید روی SERVICE_INTERFACE تنظیم شود.
  • مشخصه نام فراداده باید روی SERVICE_META_DATA تنظیم شود.
  • فایل XML فراداده باید از برچسب ریشه <offhost-apdu-service> استفاده کند.

    <service android:name=".MyOffHostApduService" android:secureElementName="eSE"
           android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE">
      <intent-filter>
          <action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/>
      </intent-filter>
      <meta-data android:name="android.nfc.cardemulation.off_host_apdu_service"
                 android:resource="@xml/apduservice"/>
    </service>

در زیر نمونه‌ای از فایل apduservice.xml مربوطه که دو شناسه برنامه را ثبت می‌کند آورده شده است:

<offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
           android:description="@string/servicedesc">
    <aid-group android:description="@string/subscription" android:category="other">
        <aid-filter android:name="F0010203040506"/>
        <aid-filter android:name="F0394148148100"/>
    </aid-group>
</offhost-apdu-service>

مشخصه android:requireDeviceUnlock برای سرویس‌های غیرمیزبان اعمال نمی‌شود، زیرا CPU میزبان در تراکنش دخیل نیست و بنابراین نمی‌تواند از اجرای تراکنش‌ها توسط عنصر امن در زمانی که دستگاه قفل است جلوگیری کند.

مشخصه android:apduServiceBanner برای سرویس‌های غیرمیزبان که برنامه‌های پرداخت هستند و باید به‌عنوان برنامه پرداخت پیش‌فرض قابل‌انتخاب باشند الزامی است.

فراخوانی سرویس خارج از میزبان

Android هرگز سرویسی را که به‌عنوان «خارج از میزبان» اعلام شده است راه‌اندازی نمی‌کند یا به آن متصل نمی‌شود، زیرا تراکنش‌های واقعی توسط عنصر امن اجرا می‌شوند و نه توسط سرویس Android. اعلام سرویس صرفاً به برنامه‌ها اجازه می‌دهد شناسه‌های برنامه موجود در عنصر امن را ثبت کنند.

HCE و امنیت

معماری HCE یک بخش اصلی از امنیت را فراهم می‌کند: چون سرویس شما با اجازه سیستم BIND_NFC_SERVICE محافظت می‌شود، فقط سیستم‌عامل می‌تواند به سرویس شما متصل شود و با آن ارتباط برقرار کند. این کار تضمین می‌کند که هر APDU که دریافت می‌کنید درواقع APDU است که توسط سیستم‌عامل از کنترل‌کننده NFC دریافت شده است، و هر APDU که ارسال می‌کنید فقط به سیستم‌عامل می‌رود، که به‌نوبه خود APDU را مستقیماً به کنترل‌کننده NFC هدایت می‌کند.

آخرین نگرانی باقی‌مانده این است که داده‌هایی را که برنامه‌تان به NFC reader ارسال می‌کند از کجا دریافت می‌کنید. این امر در طراحی HCE به‌طور عمدی جدا شده است؛ برای آن مهم نیست که داده‌ها از کجا می‌آیند، فقط مطمئن می‌شود که به‌طور ایمن به کنترل‌کننده NFC منتقل شده و به خواننده NFC ارسال می‌شوند.

برای ذخیره و بازیابی ایمن داده‌هایی که می‌خواهید از سرویس HCE خود ارسال کنید، می‌توانید مثلاً به «جعبه امن برنامه Android» تکیه کنید که داده‌های برنامه‌تان را از برنامه‌های دیگر جدا می‌کند. برای جزئیات بیشتر درباره امنیت Android، نکات امنیتی را بخوانید.

پارامترها و جزئیات پروتکل

این بخش برای توسعه‌دهندگانی جالب است که می‌خواهند بدانند دستگاه‌های HCE از چه پارامترهای پروتکلی درطول فازهای ضدتصادم و فعال‌سازی پروتکل‌های NFC استفاده می‌کنند. این کار امکان ساخت زیرساخت کارت‌خوانی را فراهم می‌کند که با دستگاه‌های Android HCE سازگار است.

فعال‌سازی و ضدتصادم پروتکل Nfc-A (ISO/IEC 14443 نوع A)

به‌عنوان بخشی از فعال‌سازی پروتکل Nfc-A، چندین فریم ردوبدل می‌شود.

در بخش اول تبادل، دستگاه HCE شناسه کاربری خود را ارائه می‌دهد؛ دستگاه‌های HCE باید شناسه کاربری تصادفی داشته باشند. این یعنی با هر تک‌ضرب، UID که به کارت‌خوان ارائه می‌شود یک UID تولیدشده به‌صورت تصادفی است. به همین دلیل، کارت‌خوان‌های NFC نباید به UID دستگاه‌های HCE به‌عنوان نوعی اصالت‌سنجی یا شناسایی وابسته باشند.

سپس NFCخوان می‌تواند با ارسال فرمان SEL_REQ دستگاه HCE را انتخاب کند. پاسخ SEL_RES دستگاه HCE حداقل بیت ششم (0x20) را تنظیم کرده است که نشان می‌دهد دستگاه از ISO-DEP پشتیبانی می‌کند. توجه داشته باشید که بیت‌های دیگر در SEL_RES نیز ممکن است تنظیم شوند، که برای مثال نشان‌دهنده پشتیبانی از پروتکل NFC-DEP (p2p) است. ازآنجایی‌که ممکن است بیت‌های دیگر تنظیم شوند، خوانندگانی که می‌خواهند با دستگاه‌های HCE تعامل داشته باشند باید صریحاً فقط بیت ششم را بررسی کنند و نباید SEL_RES کامل را با مقدار 0x20 مقایسه کنند.

فعال‌سازی ISO-DEP

پس‌از فعال شدن پروتکل Nfc-A، کارت‌خوان NFC فعال‌سازی پروتکل ISO-DEP را آغاز می‌کند. این فرمان RATS (درخواست پاسخ برای انتخاب) ارسال می‌کند. کنترل‌کننده NFC پاسخ RATS، یعنی ATS را تولید می‌کند؛ ATS توسط سرویس‌های HCE قابل‌پیکربندی نیست. بااین‌حال، پیاده‌سازی‌های HCE باید الزامات NFC Forum را برای پاسخ ATS برآورده کنند، بنابراین NFCخوان‌ها می‌توانند به این پارامترها که مطابق با الزامات NFC Forum برای هر دستگاه HCE تنظیم شده‌اند، اعتماد کنند.

بخش زیر جزئیات بیشتری درباره بایت‌های تکی پاسخ ATS ارائه‌شده توسط کنترل‌کننده NFC در دستگاه HCE ارائه می‌دهد:

  • TL: طول پاسخ ATS. نباید طولی بیشتر از ۲۰ بایت را نشان دهد.
  • T0: بیت‌های ۵، ۶، و ۷ باید در همه دستگاه‌های HCE تنظیم شوند، که نشان می‌دهد TA(1)،‏ TB(1)، و TC(1) در پاسخ ATS گنجانده شده‌اند. بیت‌های ۱ تا ۴ نشان‌دهنده FSCI است، که حداکثر اندازه قاب را کدگذاری می‌کند. در دستگاه‌های HCE، مقدار FSCI باید بین 0h و 8h باشد.
  • T(A)1: نرخ بیت بین خواننده و شبیه‌ساز را تعریف می‌کند و اینکه آیا می‌توانند نامتقارن باشند یا نه. هیچ الزامات یا تضمین‌های نرخ بیتی برای دستگاه‌های HCE وجود ندارد.
  • T(B)1: بیت‌های ۱ تا ۴ نشان‌دهنده عدد صحیح زمان محافظ قاب راه‌اندازی (SFGI) است. در دستگاه‌های HCE، مقدار SFGI باید کمتر از ۸ ساعت باشد. بیت‌های ۵ تا ۸ نشان‌دهنده عدد صحیح زمان انتظار فریم (FWI) است و زمان انتظار فریم (FWT) را کدگذاری می‌کند. در دستگاه‌های HCE،‏ FWI باید کمتر از ۸ ساعت باشد.
  • ‫T(C)1: بیت ۵ نشان‌دهنده پشتیبانی از «ویژگی‌های پروتکل پیشرفته» است. دستگاه‌های HCE ممکن است از «ویژگی‌های پروتکل پیشرفته» پشتیبانی کنند یا نکنند. بیت ۲ نشان‌دهنده پشتیبانی از DID است. دستگاه‌های HCE ممکن است از DID پشتیبانی کنند یا نکنند. بیت ۱ نشان‌دهنده پشتیبانی از NAD است. دستگاه‌های HCE نباید از NAD پشتیبانی کنند و باید بیت ۱ را روی صفر تنظیم کنند.
  • بایت‌های تاریخی: دستگاه‌های HCE ممکن است تا ۱۵ بایت تاریخی را برگردانند. NFC خوانندگانی که مایل به تعامل با سرویس‌های HCE هستند نباید هیچ فرضی درباره محتوای بایت‌های تاریخی یا حضور آن‌ها داشته باشند.

توجه داشته باشید که بسیاری‌از دستگاه‌های HCE احتمالاً با الزامات پروتکل مطابقت دارند که شبکه‌های پرداخت متحد در EMVCo در مشخصات «پروتکل ارتباطی غیرلمسی» خود مشخص کرده‌اند. بطور خاص:

  • ‫FSCI در T0 باید بین ۲ تا ۸ ساعت باشد.
  • T(A)1 باید روی 0x80 تنظیم شود، که نشان می‌دهد فقط نرخ بیت ۱۰۶ کیلوبیت بر ثانیه پشتیبانی می‌شود و نرخ بیت نامتقارن بین خواننده و شبیه‌ساز پشتیبانی نمی‌شود.
  • FWI در T(B)1 باید کمتر از یا مساوی ۷ ساعت باشد.

تبادل داده APDU

همان‌طور که قبلاً اشاره شد، پیاده‌سازی‌های HCE فقط از یک کانال منطقی پشتیبانی می‌کنند. تلاش برای انتخاب برنامه‌ها در کانال‌های منطقی مختلف در دستگاه HCE کار نمی‌کند.