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 במקום 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 מתייחס לספק SoC או 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 מתייחס לספק SoC או 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; בלבד: import PACKAGE-NAME ::types;

ה- PACKAGE-NAME עוקב אחר הפורמט בשמות החבילה . החבילה הנוכחית types.hal (אם קיימת) מיובאת אוטומטית (אל תייבא אותה במפורש).

שמות מלאים (FQN)

השתמש בשמות מלאים לייבוא ​​סוג מוגדר על ידי המשתמש רק במידת הצורך. השמט את 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 . דוגמא:

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

שמות שדות מבנה / איחוד

עבור שמות שדות מבנה / איחוד, השתמש ב- lowerCamelCase . דוגמא:

struct FooReply {
    vec<uint8_t> replyData;
}

הקלד שמות

שמות סוגים מתייחסים להגדרות מבנה / איחוד, הגדרות סוג enum ו- typedef s. לשם שם, השתמש ב- UpperCamelCase / PascalCase . דוגמאות:

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

ערכי Enum

ערכי UPPER_CASE_WITH_UNDERSCORES צריכים להיות UPPER_CASE_WITH_UNDERSCORES . כאשר מעבירים ערכי enum כארגומנטים של פונקציות ומחזירים אותם כמחזיר פונקציות, השתמש בסוג enum בפועל (לא בסוג המספר השלם הבסיסי). דוגמא:

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
};

הערה: הסוג הבסיסי של סוג enum מוכרז במפורש לאחר המעי הגס. מכיוון שהוא אינו תלוי מהדר, השימוש בסוג enum בפועל ברור יותר.

עבור שמות מוסמכים לחלוטין לערכי enum, נקודתיים משמשת בין שם סוג enum לשם הערך enum:

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

אסור שיהיו רווחים בתוך שם מלא. השתמש בשם מוסמך לחלוטין רק בעת הצורך והשמט חלקים מיותרים. דוגמא:

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

הערות

לתגובה של שורה אחת, // , /* */ , ו /** */ הם בסדר.

// This is a single line comment
/* This is also single line comment */
/** This is documentation comment */
  • השתמש /* */ להערות. בעוד 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:
     * ...
     */
    

הגש תגובות

התחל כל קובץ עם הודעת הרישוי המתאימה. עבור ליבולי HAL, זה צריך להיות רישיון AOSP Apache development/docs/copyright-templates/c.txt . זכור לעדכן את השנה ולהשתמש בתגובות מרובות שורות /* */ בסגנון כמוסבר לעיל.

באפשרותך להציב שורה ריקה לאחר הודעת הרישיון, ואחריה מידע על שינוי שינוי / גירסאות. השתמש /* */ בסגנון הערות מרובות שורות כמוסבר לעיל, מקם את השורה הריקה לאחר שינוי השינוי ואז עקוב אחר הצהרת החבילה.

הערות TODO

TODOs צריכים לכלול את TODO המחרוזת בכל הכובעים ואחריהם נקודתיים. דוגמא:

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

הערות TODO מותרות רק במהלך הפיתוח; הם לא חייבים להתקיים בממשקים שפורסמו.

הערות ממשק / פונקציה (docstrings)

השתמש /** */ למסמכי ריבוי שורות וקווים בודדים. אין להשתמש // עבור docstrings.

Docstrings לממשקים צריכים לתאר מנגנונים כלליים של הממשק, נימוקי העיצוב, המטרה וכו '. 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 s ו- @return return s עבור כל פרמטר / ערך החזרה:

  • יש להוסיף @param לכל פרמטר. אחריו צריך להיות שם הפרמטר ואז docstring.
  • יש להוסיף @return return לכל ערך החזר. אחריו צריך להיות שם ערך ההחזר ואז המסמך.

דוגמא:

/**
 * 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 עמודות.
  • מרחבים לבנים . אין רווח לבן נגרר על קווים; שורות ריקות לא יכולות להכיל רווחים לבנים.
  • רווחים לעומת כרטיסיות . השתמש רק ברווחים.
  • גודל כניסה . השתמש בארבעה רווחים לבלוקים וב 8 רווחים לעטיפות קו
  • פלטה . למעט ערכי ביאור , סוגר פתוח עובר על אותו קו כמו הקוד הקודם, אך סוגר קרוב והנקודה-פסיק הבאה תופסת את השורה כולה. דוגמה:
    interface INfc {
        close();
    };
    

הצהרת חבילה

הצהרת החבילה צריכה להיות בחלק העליון של התיק לאחר הודעת הרישיון, צריכה לתפוס את כל השורה ולא צריכה להיות מוטעת. חבילות מוכרזות בתבנית הבאה (לעיצוב שמות ראה שמות חבילות ):

package PACKAGE-NAME;

דוגמא:

package android.hardware.nfc@1.0;

הצהרות פונקציה

שם פונקציה, פרמטרים, generates , וערכי החזרה צריכים להיות על הקו הזהה אם הם מתאימים. דוגמא:

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

אם הם לא מתאימים באותה השורה, מנסה לשים פרמטרים וערכים בתמורה ברמה באותו indent ולהבחין 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();

הצהרות אנום

השתמש בכללים הבאים להצהרות enum:

  • אם הצהרות enum משותפות עם חבילה אחרת, שים את ההצהרות ב types.hal במקום להטמיע בממשק.
  • השתמש ברווח לפני ואחרי המעי הגס, ובמרווח אחרי הסוג הבסיסי לפני הסד הפתוח.
  • ערך האנומר האחרון עשוי להכיל פסיק נוסף או לא.

הצהרות מבנה

השתמש בכללים הבאים להצהרות מבנה:

  • אם הצהרות מבנה משותפות עם חבילה אחרת, שים את ההצהרות ב 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;