מצלמה

סמל HAL של מצלמת Android

שכבת ההפשטה של חומרת המצלמה (HAL) ב-Android מחברת את ממשקי ה-API ברמה גבוהה יותר של מסגרת המצלמה ב- Camera 2 לנהג ולחומרה של המצלמה. מערכת המשנה של המצלמה כוללת הטמעות של רכיבי צינור עיבוד הנתונים של המצלמה, בעוד ש-HAL של המצלמה מספק ממשקים לשימוש בהטמעה של הגרסה שלכם לרכיבים האלה.

ארכיטקטורה

בתרשים וברשימה הבאים מתוארים רכיבי ה-HAL.

הארכיטקטורה של המצלמה ב-Android

איור 1. ארכיטקטורת המצלמה

מסגרת אפליקציה
ברמת מסגרת האפליקציה נמצא הקוד של האפליקציה, שמשתמש ב-API של Camera 2 כדי לקיים אינטראקציה עם חומרת המצלמה. באופן פנימי, הקוד הזה קורא לממשקי Binder התואמים כדי לגשת לקוד המקורי שמתקשר עם המצלמה.
AIDL
ממשק ה-binder שמשויך ל-CameraService נמצא בכתובת frameworks/av/camera/aidl/android/hardware. הקוד שנוצר קורא לקוד הנייטיב ברמה נמוכה יותר כדי לקבל גישה למצלמה הפיזית, ומחזיר נתונים שמשמשים ליצירת האובייקטים CameraDevice ובסופו של דבר CameraCaptureSession ברמת המסגרת.
מסגרת נייטיב
המסגרת הזו, שנמצאת ב-frameworks/av/, מספקת מקבילה מקומית למחלקות CameraDevice ו- CameraCaptureSession. אפשר לעיין גם ב חומר העזר בנושא NDK camera2.
ממשק IPC של binder
ממשק ה-IPC binder מאפשר תקשורת מעבר לגבולות התהליכים. יש כמה כיתות של מצלמות שממוקמות בספרייה frameworks/av/camera/camera/aidl/android/hardware ומבצעות קריאה לשירות המצלמה. ICameraService הוא הממשק לשירות המצלמה, ICameraDeviceUser הוא הממשק למכשיר מצלמה ספציפי שנפתח, ICameraServiceListener וגם ICameraDeviceCallbacks הם קריאות החזרה (callbacks) של CameraService ו-CameraDevice, בהתאמה, למסגרת האפליקציה.
שירות מצלמה
שירות המצלמה, שנמצא ב-frameworks/av/services/camera/libcameraservice/CameraService.cpp, הוא הקוד בפועל שמקיים אינטראקציה עם ה-HAL.
HAL
שכבת ההפשטה של החומרה מגדירה את הממשק הסטנדרטי שאליו שירות המצלמה קורא, וצריך להטמיע אותו כדי שהחומרה של המצלמה תפעל כמו שצריך.

הטמעת ה-HAL

ה-HAL נמצא בין מנהל ההתקן של המצלמה לבין מסגרת Android ברמה גבוהה יותר, והוא מגדיר ממשק שצריך להטמיע כדי שאפליקציות יוכלו להפעיל בצורה נכונה את חומרת המצלמה. ממשקי ה-HIDL של HAL המצלמה מוגדרים בקטע hardware/interfaces/camera.

HAL אופייני שמבוסס על Binder חייב ליישם את ממשקי ה-HIDL הבאים:

  • ICameraProvider: כדי להכין רשימה של מכשירים ספציפיים ולנהל את הסטטוס שלהם.
  • ICameraDevice: ממשק המכשיר של המצלמה.
  • ICameraDeviceSession: ממשק הסשן הפעיל של מכשיר המצלמה.

יש הטמעות HIDL לדוגמה ל-CameraProvider.cpp, ל- CameraDevice.cpp ול-CameraDeviceSession.cpp. ההטמעה עוטפת HALs ישנים שעדיין משתמשים בAPI הקודם. החל מגרסה 8.0 של Android, הטמעות של Camera HAL חייבות להשתמש ב-HIDL API. לא ניתן להשתמש בממשק הקודם.

אימות קלט

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

רכיבי HAL מדור קודם

בקטע הזה מתוארת הארכיטקטורה של רכיבי ה-HAL הקודמים ואופן ההטמעה של ה-HAL. הטמעות של HAL למצלמה ב-Android מגרסה 8.0 ואילך חייבות להשתמש ב-HIDL API במקום זאת, כפי שמתואר למעלה.

ארכיטקטורה (גרסה קודמת)

בתרשים וברשימה הבאים מתוארים רכיבי ה-HAL הקודמים של המצלמה.

הארכיטקטורה של המצלמה ב-Android

איור 2. ארכיטקטורת מצלמה מדור קודם

מסגרת אפליקציה
ברמת מסגרת האפליקציה נמצא קוד האפליקציה, שמשתמש ב-API של android.hardware.Camera כדי לקיים אינטראקציה עם חומרת המצלמה. באופן פנימי, הקוד הזה קורא לכיתה JNI Glue תואמת כדי לגשת לקוד ה-Native שמתקשר עם המצלמה.
JNI
קוד ה-JNI שמשויך ל- android.hardware.Camera נמצא ב-frameworks/base/core/jni/android_hardware_Camera.cpp. הקוד הזה קורא לקוד הנייטיב ברמה נמוכה יותר כדי לקבל גישה למצלמה הפיזית, ומחזיר נתונים שמשמשים ליצירת האובייקט android.hardware.Camera ברמת המסגרת.
מסגרת נייטיב
המסגרת המקורית שמוגדרת ב-frameworks/av/camera/Camera.cpp מספקת מקבילה מקורית לכיתה android.hardware.Camera. הכיתה הזו קוראת לשרתי proxy של ה-IPC כדי לקבל גישה לשירות המצלמה.
שרתי proxy של IPC ב-binder
שרתי ה-proxy של IPC binder מאפשרים תקשורת מעבר לגבולות התהליכים. יש שלוש כיתות של מסמכי קישור למצלמה שנמצאות בתיקייה frameworks/av/camera, שמבצעות קריאה לשירות המצלמה. ICameraService הוא הממשק לשירות המצלמה,‏ ICamera הוא הממשק למכשיר מצלמה ספציפי שנפתח, ו-ICameraClient הוא הממשק של המכשיר חזרה למסגרת האפליקציה.
שירות מצלמה
שירות המצלמה, שנמצא ב-frameworks/av/services/camera/libcameraservice/CameraService.cpp, הוא הקוד בפועל שמקיים אינטראקציה עם ה-HAL.
HAL
שכבת ההפשטה של החומרה מגדירה את הממשק הסטנדרטי שאליו שירות המצלמה קורא, וצריך להטמיע אותו כדי שהחומרה של המצלמה תפעל כמו שצריך.
דרייבר ליבה
הדרייבר של המצלמה יוצר אינטראקציה עם חומרת המצלמה בפועל ועם ההטמעה שלכם של HAL. המצלמה והדרייבר חייבים לתמוך בפורמטים של תמונות YV12 ו-NV21 כדי לספק תמיכה בתצוגה מקדימה של תמונת המצלמה במסך ובצילום וידאו.

הטמעת HAL (קודם)

ה-HAL נמצא בין מנהל ההתקן של המצלמה לבין מסגרת Android ברמה גבוהה יותר, והוא מגדיר ממשק שצריך להטמיע כדי שאפליקציות יוכלו להפעיל בצורה נכונה את חומרת המצלמה. ממשק ה-HAL מוגדר בקובצי הכותרת hardware/libhardware/include/hardware/camera.h ו-hardware/libhardware/include/hardware/camera_common.h.

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

camera.h מכיל קוד שתואם ל- android.hardware.Camera. קובץ הכותרת הזה מכריז על מבנה camera_device שמכיל מבנה camera_device_ops עם הפניות לפונקציות שמטמיעות את ממשק ה-HAL. במאמר frameworks/av/include/camera/CameraParameters.h מוסבר על הפרמטרים של המצלמה שמפתחים יכולים להגדיר. הפרמטרים האלה מוגדרים באמצעות הפונקציה ש-int (*set_parameters)(struct camera_device *, const char *parms) מפנה אליה ב-HAL.

דוגמה להטמעת HAL מופיעה בהטמעה של HAL ל-Galaxy Nexus בקטע hardware/ti/omap4xxx/camera.

הגדרת הספרייה המשותפת

מגדירים את מערכת ה-build של Android כך שתארוז בצורה נכונה את הטמעת ה-HAL בספרייה משותפת ותעתיק אותה למיקום המתאים, על ידי יצירת קובץ Android.mk:

  1. יוצרים ספרייה device/<company_name>/<device_name>/camera שתכלול את קובצי המקור של הספרייה.
  2. יוצרים קובץ Android.mk כדי ליצור את הספרייה המשותפת. מוודאים שהשורות הבאות מופיעות בקובץ ה-makefile:
    LOCAL_MODULE := camera.<device_name>
    LOCAL_MODULE_RELATIVE_PATH := hw
    

    שם הספרייה צריך להיות camera.<device_name> (הסיומת .so מצורפת באופן אוטומטי) כדי שמערכת Android תוכל לטעון את הספרייה בצורה נכונה. לדוגמה, אפשר לעיין בקובץ ה-makefile של מצלמת Galaxy Nexus שנמצא ב-hardware/ti/omap4xxx/Android.mk.

  3. כדי לציין שלמכשיר יש תכונות מצלמה, מעתיקים את קובצי ה-XML הנדרשים של התכונות לתיקייה frameworks/native/data/etc עם קובץ ה-makefile של המכשיר. לדוגמה, כדי לציין שלמכשיר יש פלאש מצלמה והוא יכול לבצע פוקוס אוטומטי, מוסיפים את השורות הבאות לקובץ ה-makefile‏ <device>/<company_name>/<device_name>/device.mk של המכשיר:
    PRODUCT_COPY_FILES := \ ...
    
    PRODUCT_COPY_FILES += \
    frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \
    

    דוגמה לקובץ makefile של מכשיר מופיעה בקטע device/samsung/tuna/device.mk.

  4. מצהירים על היכולות של המצלמה בפורמט, ברזולוציה ובקודק המדיה בקובצי XML‏ device/<company_name>/<device_name>/media_profiles.xml ו-device/<company_name>/<device_name>/media_codecs.xml. פרטים נוספים זמינים במאמר חשיפת קודיקס למסגרת.
  5. מוסיפים את השורות הבאות לקובץ ה-makefile‏ device/<company_name>/<device_name>/device.mk של המכשיר כדי להעתיק את הקבצים media_profiles.xml ו-media_codecs.xml למיקום המתאים:
    # media config xml file
    PRODUCT_COPY_FILES += \
        <device>/<company>/<device>/media_profiles.xml:system/etc/media_profiles.xml
    
    # media codec config xml file
    PRODUCT_COPY_FILES += \
        <device>/<company>/<device>/media_codecs.xml:system/etc/media_codecs.xml
    
  6. כדי לכלול את אפליקציית המצלמה בקובץ האימג' של המערכת של המכשיר, מציינים אותה במשתנה PRODUCT_PACKAGES בקובץ ה-makefile‏ device/<company>/<device>/device.mk של המכשיר:
    PRODUCT_PACKAGES := \
    Gallery2 \
    ...