אנדרואיד 8.0 ארכיב מחדש את מערכת ההפעלה אנדרואיד כדי להגדיר ממשקים ברורים בין פלטפורמת אנדרואיד שאינה תלויה במכשיר לבין קוד ספציפי למכשיר ולספק. אנדרואיד כבר הגדירה ממשקים רבים כאלה בצורה של ממשקי HAL, שהוגדרו ככותרות C hardware/libhardware
. HIDL החליף ממשקי HAL אלה בממשקים יציבים ומותקנים, שיכולים להיות ב- Java (שתואר להלן) או כממשקי HIDL בצד הלקוח והשרת ב- C ++ .
ממשקי HIDL מיועדים לשימוש בעיקר מקוד מקורי, וכתוצאה מכך HIDL מתמקדת בייצור אוטומטי של קוד יעיל ב- C ++. עם זאת, ממשקי HIDL חייבים להיות מסוגלים לשמש ישירות גם מג'אווה שכן ככל הנראה בחלק מתתי מערכות האנדרואיד (כגון טלפוניה) יהיו ממשקי Java HIDL.
העמודים בחלק זה מתארים את חזית ה- Java עבור ממשקי HIDL, מפרטים כיצד ליצור, לרשום ולהשתמש בשירותים, ולהסביר כיצד HALs ולקוחות HAL הכתובים ב- Java מתקשרים עם מערכת HIDL RPC.
להיות לקוח
זוהי דוגמה ללקוח עבור ממשק IFoo
בחבילה android.hardware.foo@1.0
שרשום default
לשירות ושירות נוסף עם שם השירות המותאם אישית second_impl
.
הוספת ספריות
עליך להוסיף תלות בספריית HIDL המתאימה אם ברצונך להשתמש בה. בדרך כלל זוהי ספרייה סטטית:
// in Android.bp static_libs: [ "android.hardware.foo-V1.0-java", ], // in Android.mk LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java
אם אתה יודע שאתה כבר משיג תלות בספריות אלה, אתה יכול גם להשתמש בקישור משותף:
// in Android.bp libs: [ "android.hardware.foo-V1.0-java", ], // in Android.mk LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java
שיקולים נוספים להוספת ספריות באנדרואיד 10
אם יש לך אפליקציית מערכת / ספק המכוונת ל- Android 10 ואילך, עליך לכלול באופן סטטי ספריות אלה. עבור אפליקציות ישנות יותר, ההתנהגות הישנה נשמרת. לחלופין, ניתן להשתמש רק בכיתות HIDL מ- JAR מותאמות אישית המותקנות בהתקן עם ממשקי API יציבים של Java הנגישים באמצעות מנגנון uses-library
הקיים עבור אפליקציות מערכת. על מנת לחסוך מקום במכשיר, זו הגישה המומלצת. לפרטים נוספים, ראה יישום ספריית Java SDK .
החל מ -10, קיימות גם גרסאות "רדודות" של ספריות אלה. אלה כוללים את הכיתה המדוברת, אך אינם כוללים אף אחד מהשיעורים התלויים. לדוגמה, android.hardware.foo-V1.0-java-shallow
כולל שיעורים בחבילה foo, אך אינו כולל שיעורים ב- android.hidl.base-V1.0-java
, המכיל את מחלקת הבסיס של כל HIDL ממשקים. אם אתה יוצר ספריה שכבר יש לה שיעורי בסיס של הממשק המועדף כתלות, אתה יכול להשתמש בפעולות הבאות:
// in Android.bp static_libs: [ "android.hardware.foo-V1.0-java-shallow", ], // in Android.mk LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow
ספריות בסיס HIDL ומנהלים אינן זמינות עוד בנתיב האתחול. במקום זאת, הם הועברו למרחב שמות חדש עם jarjar
. מודולים בשביל הכיתה של האתחול המשתמשים ב- HIDL צריכים להשתמש בגרסאות הרדודות של ספריות אלה וכן להוסיף jarjar_rules: ":framework-jarjar-rules"
ל- Android.bp
שלהם על מנת למנוע קוד כפול ושימוש באפליקציות מערכת / ספקים להשתמש בממשקי API מוסתרים. .
שינוי מקור ה- Java שלך
יש רק גרסה אחת ( @1.0
) של שירות זה, ולכן קוד זה מאחזר רק את הגרסה הזו. ראה הרחבות ממשק כיצד להתמודד עם מספר גרסאות שונות של השירות.
import android.hardware.foo.V1_0.IFoo; ... // retry to wait until the service starts up if it is in the manifest IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IFoo anotherServer = IFoo.getService("second_impl", true /* retry */); server.doSomething(…);
מתן שירות
קוד מסגרת בג'אווה עשוי להזדקק לשרת ממשקים כדי לקבל שיחות חוזר אסינכרוניות מ- HAL.
עבור ממשק IFooCallback
בגרסה 1.0 של חבילת android.hardware.foo
, אתה יכול ליישם את הממשק שלך ב- Java באמצעות השלבים הבאים:
- הגדר את הממשק שלך ב- HIDL.
- פתח
/tmp/android/hardware/foo/IFooCallback.java
כהפניה. - צור מודול חדש ליישום Java שלך.
- בדוק את המחלקה המופשטת
android.hardware.foo.V1_0.IFooCallback.Stub
, ואז כתוב מחלקה חדשה כדי להרחיב אותה וליישם את השיטות המופשטות.
הצגת קבצים שנוצרו אוטומטית
כדי להציג את הקבצים שנוצרו אוטומטית, הפעל:
hidl-gen -o /tmp -Ljava \ -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0
פקודות אלה מייצרות את הספרייה /tmp/android/hardware/foo/1.0
. עבור hardware/interfaces/foo/1.0/IFooCallback.hal
הקבצים hardware/interfaces/foo/1.0/IFooCallback.hal
, זה מייצר את הקובץ /tmp/android/hardware/foo/1.0/IFooCallback.java
, /tmp/android/hardware/foo/1.0/IFooCallback.java
את ממשק Java, קוד ה- proxy וה- stubs (שניהם proxy ותלים תואמים את הממשק).
-Lmakefile
מייצר את הכללים המריצים פקודה זו בזמן הבנייה ומאפשרים לך לכלול את android.hardware.foo-V1.0-java
ולקשר כנגד הקבצים המתאימים. סקריפט שעושה זאת באופן אוטומטי לפרויקט מלא בממשקים ניתן למצוא hardware/interfaces/update-makefiles.sh
. הנתיבים בדוגמה זו הם יחסית; חומרה / ממשקים יכולים להיות ספריה זמנית מתחת לעץ הקוד שלך כדי לאפשר לך לפתח HAL לפני פרסום זה.
הפעלת שירות
ה- HAL מספקת את IFoo
ממשק, אשר חייב לעשות הגיעו ליעדן אסינכרוני למסגרת מעל IFooCallback
ממשק. ממשק IFooCallback
אינו רשום בשמו כשירות שניתן לגלות; במקום זאת, IFoo
חייבת להכיל שיטה כגון setFooCallback(IFooCallback x)
.
כדי להגדיר IFooCallback
מגירסה 1.0 של android.hardware.foo
החבילה, להוסיף android.hardware.foo-V1.0-java
כדי Android.mk
. הקוד להפעלת השירות הוא:
import android.hardware.foo.V1_0.IFoo; import android.hardware.foo.V1_0.IFooCallback.Stub; .... class FooCallback extends IFooCallback.Stub { // implement methods } .... // Get the service you will be receiving callbacks from. // This also starts the threadpool for your callback service. IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available .... // This must be a persistent instance variable, not local, // to avoid premature garbage collection. FooCallback mFooCallback = new FooCallback(); .... // Do this once to create the callback service and tell the "foo-bar" service server.setFooCallback(mFooCallback);
הרחבות ממשק
בהנחה ששירות נתון מיישם את ממשק IFoo
בכל המכשירים, ייתכן שבמכשיר מסוים השירות עשוי לספק יכולות נוספות המיושמות בסיומת הממשק IBetterFoo
, כדלקמן:
interface IFoo { ... }; interface IBetterFoo extends IFoo { ... };
קוד שיחה המודע לממשק המורחב יכול להשתמש בשיטת Java של castFrom()
כדי להטיל את ממשק הבסיס בבטחה לממשק המורחב:
IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IBetterFoo extendedService = IBetterFoo.castFrom(baseService); if (extendedService != null) { // The service implements the extended interface. } else { // The service implements only the base interface. }