Google is committed to advancing racial equity for Black communities. See how.
ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

دليل نمط التعليمات البرمجية

يشبه نمط كود HIDL كود C ++ في إطار عمل Android ، مع مسافات بادئة 4 وأسماء ملفات مختلطة. تتشابه إقرارات الحزمة والواردات وسلاسل المستندات مع تلك الموجودة في Java ، مع بعض التعديلات الطفيفة.

الأمثلة التالية ل IFoo.hal و types.hal توضيح أساليب كود HIDL وتوفير وصلات سريعة للتفاصيل على كل نمط ( IFooClientCallback.hal ، IBar.hal ، و IBaz.hal تم حذف).

hardware/interfaces/foo/1.0/IFoo.hal
/*
 * (License Notice)
 */

package android.hardware.foo@1.0;

import android.hardware.bar@1.0::IBar;

import IBaz;
import IFooClientCallback;

/**
 * IFoo is an interface that…
 */
interface IFoo {

    /**
     * This is a multiline docstring.
     *
     * @return result 0 if successful, nonzero otherwise.
     */
     foo() generates (FooStatus result);

    /**
     * Restart controller by power cycle.
     *
     * @param bar callback interface that…
     * @return result 0 if successful, nonzero otherwise.
     */
    powerCycle(IBar bar) generates (FooStatus result);

    /** Single line docstring. */
    baz();


    /**
     * The bar function.
     *
     * @param clientCallback callback after function is called
     * @param baz related baz object
     * @param data input data blob
     */
    bar(IFooClientCallback clientCallback,
        IBaz baz,
        FooData data);

};
hardware/interfaces/foo/1.0/types.hal
/*
 * (License Notice)
 */

package android.hardware.foo@1.0;

/** Replied status. */
enum Status : int32_t {
    OK,
    /* invalid arguments */
    ERR_ARG,
    /* note, no transport related errors */
    ERR_UNKNOWN = -1,
};

struct ArgData {
    int32_t[20]  someArray;
    vec<uint8_t> data;
};

اصطلاحات التسمية

يجب أن تكون أسماء الوظائف وأسماء المتغيرات وأسماء الملفات وصفية ؛ تجنب الإفراط في الاختصار. تعامل مع الاختصارات على أنها كلمات (على سبيل المثال ، استخدم INfc بدلاً من INFC ).

بنية الدليل وتسمية الملفات

يجب أن تظهر بنية الدليل على النحو التالي:

  • ROOT-DIRECTORY
    • MODULE
      • SUBMODULE (اختياري ، يمكن أن يكون أكثر من مستوى)
        • VERSION
          • Android.mk
          • I INTERFACE_1 .hal
          • I INTERFACE_2 .hal
          • I INTERFACE_N .hal
          • types.hal (اختياري)

أين:

  • ROOT-DIRECTORY هو:
    • hardware/interfaces حزم HIDL الأساسية.
    • vendor/ VENDOR /interfaces لحزم البائعين، حيث VENDOR يشير إلى بائع شركة نفط الجنوب أو OEM / ODM.
  • يجب أن تكون MODULE عبارة عن كلمة صغيرة واحدة تصف النظام الفرعي (مثل nfc ). إذا كانت هناك حاجة إلى أكثر من كلمة واحدة ، فاستخدم SUBMODULE المتداخلة. يمكن أن يكون هناك أكثر من مستوى واحد من التعشيش.
  • يجب أن يكون VERSION هو نفس الإصدار بالضبط (major.minor) كما هو موضح في الإصدارات .
  • يجب أن يكون I INTERFACE_X هو اسم الواجهة مع UpperCamelCase / PascalCase (مثل INfc ) كما هو موضح في أسماء الواجهة .

مثال:

  • hardware/interfaces
    • nfc
      • 1.0
        • Android.mk
        • INfc.hal
        • INfcClientCallback.hal
        • types.hal

ملاحظة: يجب أن تحتوي جميع الملفات على أذونات غير قابلة للتنفيذ (في Git).

أسماء الحزم

يجب أن تستخدم أسماء الحزم تنسيق الاسم المؤهل بالكامل (FQN) التالي (المشار إليه باسم PACKAGE-NAME ):

PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION

أين:

  • PACKAGE هي الحزمة التي ترسم خرائط لـ ROOT-DIRECTORY . على وجه الخصوص ، PACKAGE هي:
    • android.hardware لحزم HIDL الأساسية (تعيين hardware/interfaces ).
    • vendor. VENDOR .hardware حزم البائعين، حيث VENDOR يشير إلى بائع شركة نفط الجنوب أو OEM / ODM (رسم الخرائط ل vendor/ VENDOR /interfaces ).
  • MODULE [. SUBMODULE [. SUBMODULE […]]]@ VERSION هي نفس أسماء المجلدات في البنية الموضحة في بنية الدليل .
  • يجب أن تكون أسماء الحزم صغيرة. إذا كانت snake_case من أكثر من كلمة واحدة ، فيجب استخدام الكلمات snake_case فرعية أو كتابتها في snake_case .
  • لا يسمح بمسافات.

تُستخدم FQN دائمًا في إقرارات الحزمة.

إصدارات

يجب أن يكون للإصدارات التنسيق التالي:

MAJOR.MINOR

يجب أن يكون كلا الإصدارين MAJOR و MINOR عددًا صحيحًا واحدًا. يستخدم HIDL قواعد الإصدار الدلالية .

الواردات

يكون للاستيراد أحد التنسيقات الثلاثة التالية:

  • واردات الحزمة الكاملة: import PACKAGE-NAME ;
  • الواردات الجزئية: import PACKAGE-NAME :: UDT ; (أو ، إذا كان النوع المستورد في نفس الحزمة ، قم import UDT ;
  • استيراد الأنواع فقط: import PACKAGE-NAME ::types;

يتبع PACKAGE-NAME التنسيق في أسماء الحزم . يتم types.hal الحزمة الحالية (إن وجدت) تلقائيًا (لا تستوردها صراحةً).

أسماء مؤهلة بالكامل (FQNs)

استخدم الأسماء المؤهلة بالكامل لاستيراد نوع معرف من قبل المستخدم فقط عند الضرورة. احذف PACKAGE-NAME إذا كان نوع الاستيراد في نفس الحزمة. يجب ألا يحتوي FQN على مسافات. مثال على اسم مؤهل بالكامل:

android.hardware.nfc@1.0::INfcClientCallback

في ملف آخر ضمن android.hardware.nfc@1.0 ، ارجع إلى الواجهة أعلاه كـ INfcClientCallback . خلاف ذلك ، استخدم فقط الاسم المؤهل بالكامل.

تجميع وترتيب الواردات

استخدم سطرًا فارغًا بعد إعلان الحزمة (قبل الاستيراد). يجب أن يحتل كل استيراد سطرًا واحدًا ولا يجب وضع مسافة بادئة له. استيراد المجموعة بالترتيب التالي:

  1. حزم android.hardware الأخرى (تستخدم أسماء مؤهلة بالكامل).
  2. vendor. VENDOR آخر vendor. VENDOR حزم vendor. VENDOR (استخدم أسماء مؤهلة بالكامل).
    • يجب أن يكون كل بائع مجموعة.
    • ترتيب البائعين أبجديا.
  3. الواردات من واجهات أخرى في نفس الحزمة (استخدم أسماء بسيطة).

استخدم خطًا فارغًا بين المجموعات. داخل كل مجموعة ، قم بفرز الواردات أبجديًا. مثال:

import android.hardware.nfc@1.0::INfc;
import android.hardware.nfc@1.0::INfcClientCallback;

/* Importing the whole module. */
import vendor.barvendor.bar@3.1;

import vendor.foovendor.foo@2.2::IFooBar;
import vendor.foovendor.foo@2.2::IFooFoo;

import IBar;
import IFoo;

أسماء الواجهة

يجب أن تبدأ أسماء الواجهة بـ I ، متبوعًا UpperCamelCase / PascalCase . يجب تحديد واجهة تحمل اسم IFoo في الملف IFoo.hal . يمكن أن يحتوي هذا الملف على تعريفات لواجهة IFoo فقط (يجب أن تكون الواجهة I NAME في I NAME .hal ).

المهام

بالنسبة لأسماء الدوال lowerCamelCase وأسماء متغيرات الإرجاع ، استخدم lowerCamelCase . مثال:

open(INfcClientCallback clientCallback) generates (int32_t retVal);
oneway pingAlive(IFooCallback cb);

أسماء الحقول الهيكلية / الاتحاد

بالنسبة لأسماء الحقول الهيكلية / lowerCamelCase ، استخدم lowerCamelCase . مثال:

struct FooReply {
    vec<uint8_t> replyData;
}

اكتب الأسماء

تشير أسماء الأنواع إلى تعريفات البنية / الاتحاد ، وتعريفات نوع التعداد ، و typedef s. لهذه الاسم ، استخدم UpperCamelCase / PascalCase . أمثلة:

enum NfcStatus : int32_t {
    /*...*/
};
struct NfcData {
    /*...*/
};

عد القيم

يجب أن تكون قيم التعداد UPPER_CASE_WITH_UNDERSCORES . عند تمرير قيم التعداد كوسائط دالة وإعادتها كإرجاع دالة ، استخدم نوع التعداد الفعلي (وليس نوع العدد الصحيح الأساسي). مثال:

enum NfcStatus : int32_t {
    HAL_NFC_STATUS_OK               = 0,
    HAL_NFC_STATUS_FAILED           = 1,
    HAL_NFC_STATUS_ERR_TRANSPORT    = 2,
    HAL_NFC_STATUS_ERR_CMD_TIMEOUT  = 3,
    HAL_NFC_STATUS_REFUSED          = 4
};

ملاحظة: يتم الإعلان صراحة عن النوع الأساسي لنوع التعداد بعد النقطتين. نظرًا لأنه لا يعتمد على المترجم ، فإن استخدام نوع التعداد الفعلي أكثر وضوحًا.

بالنسبة للأسماء المؤهلة بالكامل لقيم التعداد ، يتم استخدام نقطتين بين اسم نوع التعداد واسم قيمة التعداد:

PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME

يجب ألا تكون هناك مسافات داخل اسم مؤهل بالكامل. استخدم اسمًا مؤهلًا بالكامل فقط عند الضرورة وتجاهل الأجزاء غير الضرورية. مثال:

android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK

تعليقات

للحصول على تعليق من سطر واحد ، لا بأس // و /* */ و /** */ .

0 بيف 27280
  • استخدم /* */ للتعليق. بينما يدعم HIDL // للتعليقات ، يتم تثبيطهم لأنهم لا يظهرون في المخرجات التي تم إنشاؤها.
  • استخدم /** */ للوثائق التي تم إنشاؤها. يمكن تطبيق هذه فقط على إعلانات النوع والطريقة والحقل وقيمة التعداد. مثال:
    /** Replied status */
    enum TeleportStatus {
        /** Object entirely teleported. */
        OK              = 0,
        /** Methods return this if teleportation is not completed. */
        ERROR_TELEPORT  = 1,
        /**
         * Teleportation could not be completed due to an object
         * obstructing the path.
         */
        ERROR_OBJECT    = 2,
        ...
    }
    
  • ابدأ التعليقات متعددة الأسطر باستخدام /** في سطر منفصل. استخدم * في بداية كل سطر. قم بإنهاء التعليق بـ */ في سطر منفصل ، مع محاذاة العلامات النجمية. مثال:
    /**
     * My multi-line
     * comment
     */
    
  • يجب أن يبدأ إشعار الترخيص وسجلات التغيير سطرًا جديدًا بـ /* (علامة نجمية واحدة) ، استخدم * في بداية كل سطر ، ووضع */ في السطر الأخير بمفرده (يجب محاذاة العلامات النجمية). مثال:
    /*
     * Copyright (C) 2017 The Android Open Source Project
     * ...
     */
    
    /*
     * Changelog:
     * ...
     */
    

تعليقات الملف

ابدأ كل ملف بإشعار الترخيص المناسب. بالنسبة لـ HALs الأساسية ، يجب أن يكون هذا ترخيص AOSP Apache في development/docs/copyright-templates/c.txt . تذكر تحديث السنة واستخدام /* */ style التعليقات متعددة الأسطر كما هو موضح أعلاه.

يمكنك اختياريًا وضع سطر فارغ بعد إشعار الترخيص ، متبوعًا بمعلومات سجل التغيير / الإصدار. استخدم /* */ style Multi-line comments كما هو موضح أعلاه ، ضع السطر الفارغ بعد التغيير ، ثم اتبع إعلان الحزمة.

تعليقات TODO

يجب أن تتضمن TODO سلسلة TODO في جميع الأحرف الاستهلالية متبوعة بنقطتين. مثال:

// TODO: remove this code before foo is checked in.

يُسمح بتعليقات TODO فقط أثناء التطوير ؛ يجب ألا تكون موجودة في الواجهات المنشورة.

واجهة / تعليقات الوظيفة (docstrings)

استخدم /** */ لسلاسل وثائقية متعددة الأسطر وسطر واحد. لا تستخدم // لسلاسل الوثائق.

يجب أن تصف الوثائق الخاصة بالواجهات الآليات العامة للواجهة ، والأساس المنطقي للتصميم ، والغرض ، وما إلى ذلك. يجب أن تكون سلاسل الدوال للوظائف محددة للوظيفة (يتم وضع التوثيق على مستوى الحزمة في ملف README في دليل الحزمة).

/**
 * IFooController is the controller for foos.
 */
interface IFooController {
    /**
     * Opens the controller.
     *
     * @return status HAL_FOO_OK if successful.
     */
    open() generates (FooStatus status);

    /** Close the controller. */
    close();
};

يجب إضافة @param الصورة و @return الصورة لكل قيمة المعلمة / عودة:

  • يجب إضافة @param لكل معلمة. يجب أن يتبعه اسم المعلمة ثم docstring.
  • @return يجب أن يضاف لكل قيمة الإرجاع. يجب أن يتبعه اسم القيمة المعادة ثم docstring.

مثال:

/**
 * Explain what foo does.
 *
 * @param arg1 explain what arg1 is
 * @param arg2 explain what arg2 is
 * @return ret1 explain what ret1 is
 * @return ret2 explain what ret2 is
 */
foo(T arg1, T arg2) generates (S ret1, S ret2);

تنسيق

تتضمن قواعد التنسيق العامة ما يلي:

  • طول الخط . يجب ألا يزيد طول كل سطر من النص عن 100 عمود.
  • المسافات . لا توجد مسافة بيضاء زائدة على الخطوط ؛ يجب ألا تحتوي الأسطر الفارغة على مسافات.
  • مسافات مقابل علامات التبويب . استخدم المسافات فقط.
  • حجم المسافة البادئة . استخدم 4 مسافات للكتل و 8 مسافات للالتفاف الخطي
  • تستعد . باستثناء قيم التعليق التوضيحي ، يسير القوس المفتوح على نفس السطر مثل الكود السابق ولكن قوس قريب والفاصلة المنقوطة التالية تحتل السطر بأكمله. مثال:
    interface INfc {
        close();
    };
    

إعلان الحزمة

يجب أن يكون إعلان الحزمة في أعلى الملف بعد إشعار الترخيص ، ويجب أن يشغل السطر بالكامل ، ويجب ألا يتم وضع مسافة بادئة له. يتم التصريح عن الحزم باستخدام التنسيق التالي (لتنسيق الاسم ، راجع أسماء الحزم ):

package PACKAGE-NAME;

مثال:

package android.hardware.nfc@1.0;

إقرارات الوظيفة

يجب أن تكون قيم اسم الوظيفة والمعلمات generates والإرجاع على نفس السطر إذا كانت مناسبة. مثال:

interface IFoo {
    /** ... */
    easyMethod(int32_t data) generates (int32_t result);
};

إذا لم تتلاءم مع نفس السطر ، فحاول وضع المعلمات وقيم الإرجاع في نفس مستوى المسافة البادئة وتمييز generate لمساعدة القارئ على رؤية المعلمات وقيم الإرجاع بسرعة. مثال:

interface IFoo {
    suchALongMethodThatCannotFitInOneLine(int32_t theFirstVeryLongParameter,
                                          int32_t anotherVeryLongParameter);
    anEvenLongerMethodThatCannotFitInOneLine(int32_t theFirstLongParameter,
                                             int32_t anotherVeryLongParameter)
                                  generates (int32_t theFirstReturnValue,
                                             int32_t anotherReturnValue);
    superSuperSuperSuperSuperSuperSuperLongMethodThatYouWillHateToType(
            int32_t theFirstVeryLongParameter, // 8 spaces
            int32_t anotherVeryLongParameter
        ) generates (
            int32_t theFirstReturnValue,
            int32_t anotherReturnValue
        );
    /* method name is even shorter than 'generates' */
    foobar(AReallyReallyLongType aReallyReallyLongParameter,
           AReallyReallyLongType anotherReallyReallyLongParameter)
        generates (ASuperLongType aSuperLongReturnValue, // 4 spaces
                   ASuperLongType anotherSuperLongReturnValue);
}

تفاصيل اضافية:

  • يكون القوس المفتوح دائمًا على نفس السطر مثل اسم الوظيفة.
  • لا توجد مسافات بين اسم الوظيفة والأقواس المفتوحة.
  • لا توجد مسافات بين الأقواس والمعلمات إلا في حالة وجود خط تغذية بينها.
  • إذا كان generates على نفس السطر مثل قوس الإغلاق السابق ، فاستخدم مسافة سابقة. إذا كان generates على نفس السطر مثل قوس الفتح التالي ، فاتبعه بمسافة.
  • قم بمحاذاة جميع المعلمات وقيم الإرجاع (إن أمكن).
  • المسافة البادئة الافتراضية هي 4 مسافات.
  • تتم محاذاة المعلمات المغلفة مع المعلمات الأولى في السطر السابق ، وإلا فسيكون لها مسافة بادئة تبلغ 8 مسافات.

شروح

استخدم التنسيق التالي للتعليقات التوضيحية:

@annotate(keyword = value, keyword = {value, value, value})

رتّب التعليقات التوضيحية أبجديًا واستخدم المسافات حول علامات التساوي. مثال:

@callflow(key = value)
@entry
@exit

تأكد من احتلال التعليق التوضيحي للسطر بأكمله. أمثلة:

/* Good */
@entry
@exit

/* Bad */
@entry @exit

إذا كانت التعليقات التوضيحية لا يمكن احتواؤها في نفس السطر ، فضع مسافة بادئة بمقدار 8 مسافات. مثال:

@annotate(
        keyword = value,
        keyword = {
                value,
                value
        },
        keyword = value)

إذا كان لا يمكن احتواء مجموعة القيم بأكملها في نفس السطر ، فضع فواصل الأسطر بعد الأقواس المفتوحة { وبعد كل فاصلة داخل المصفوفة. ضع قوس الإغلاق بعد القيمة الأخيرة مباشرة. لا تضع الأقواس إذا كانت هناك قيمة واحدة فقط.

إذا كان من الممكن احتواء مجموعة القيم بأكملها في نفس السطر ، فلا تستخدم مسافات بعد الأقواس المفتوحة وقبل إغلاق الأقواس واستخدم مسافة واحدة بعد كل فاصلة. أمثلة:

/* Good */
@callflow(key = {"val", "val"})

/* Bad */
@callflow(key = { "val","val" })

يجب ألا تكون هناك أسطر فارغة بين التعليقات التوضيحية وإعلان الوظيفة. أمثلة:

/* Good */
@entry
foo();

/* Bad */
@entry

foo();

تعداد الإعلانات

استخدم القواعد التالية لإقرارات التعداد:

  • إذا تمت مشاركة تعريفات التعداد مع حزمة أخرى ، فضع الإعلانات في types.hal بدلاً من التضمين داخل واجهة.
  • استخدم مسافة قبل القولون وبعده ، ومسافة بعد النوع الأساسي قبل الدعامة المفتوحة.
  • قد تحتوي أو لا تحتوي قيمة التعداد الأخيرة على فاصلة إضافية.

إقرارات الهيكل

استخدم القواعد التالية للإعلانات الهيكلية:

  • إذا تمت مشاركة تعريفات البنية مع حزمة أخرى ، فضع الإعلانات في types.hal بدلاً من التضمين داخل واجهة.
  • استخدم مسافة بعد اسم نوع الهيكل قبل القوس المفتوح.
  • محاذاة أسماء الحقول (اختياري). مثال:
    struct MyStruct {
        vec<uint8_t>   data;
        int32_t        someInt;
    }
    

إقرارات الصفيف

لا تضع مسافات بين الآتي:

  • نوع العنصر وقوس مربع مفتوح.
  • فتح قوس مربع وحجم الصفيف.
  • حجم الصفيف وإغلاق قوس مربع.
  • إغلاق القوس المربع والقوس المربع المفتوح التالي ، في حالة وجود أكثر من بُعد واحد.

أمثلة:

/* Good */
int32_t[5] array;

/* Good */
int32_t[5][6] multiDimArray;

/* Bad */
int32_t [ 5 ] [ 6 ] array;

ثلاثة أبعاد

لا تضع مسافات بين الآتي:

  • vec وقوس زاوية مفتوحة.
  • قوس فتح الزاوية ونوع العنصر ( استثناء: نوع العنصر هو أيضًا vec ).
  • نوع العنصر وقوس زاوية الإغلاق ( استثناء: نوع العنصر هو أيضًا vec ) .

أمثلة:

/* Good */
vec<int32_t> array;

/* Good */
vec<vec<int32_t>> array;

/* Good */
vec< vec<int32_t> > array;

/* Bad */
vec < int32_t > array;

/* Bad */
vec < vec < int32_t > > array;