מצלמה

סמל של Android Camera HAL

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

ארכיטקטורה

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

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

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

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

הטמעה של HAL

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

בדרך כלל, בממשק HAL עם Binder צריך להטמיע את הממשקים הבאים של HIDL:

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

אימות קלט

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

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

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

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

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

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

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

app framework
ברמת מסגרת האפליקציה נמצא הקוד של האפליקציה, שמשתמש ב-API‏ android.hardware.Camera כדי ליצור אינטראקציה עם חומרת המצלמה. באופן פנימי, הקוד הזה קורא למחלקת דבק JNI תואמת כדי לגשת לקוד ה-Native שמתקשר עם המצלמה.
JNI
קוד ה-JNI שמשויך ל- android.hardware.Camera נמצא ב-frameworks/base/core/jni/android_hardware_Camera.cpp. הקוד הזה קורא לקוד Native ברמה הנמוכה כדי לקבל גישה למצלמה הפיזית ומחזיר נתונים שמשמשים ליצירת האובייקט android.hardware.Camera ברמת ה-framework.
native framework
המסגרת המקורית שמוגדרת ב-frameworks/av/camera/Camera.cpp מספקת מקבילה מקורית למחלקה android.hardware.Camera. המחלקות האלה קוראות ל-IPC binder proxies כדי לקבל גישה לשירות המצלמה.
שרתי proxy של IPC ל-Binder
פרוקסי של 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 contains code that corresponds to 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 מופיעה בהטמעה של Galaxy Nexus HAL ב-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 של המכשיר. לדוגמה, כדי לציין שלמכשיר יש פלאש במצלמה והוא יכול להתמקד אוטומטית, מוסיפים את השורות הבאות לקובץ <device>/<company_name>/<device_name>/device.mk makefile של המכשיר:
    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.xmldevice/<company_name>/<device_name>/media_codecs.xmldevice/<company_name>/<device_name>/media_profiles.xml. פרטים נוספים זמינים במאמר בנושא חשיפת קודקים למסגרת.
  5. כדי להעתיק את הקבצים media_profiles.xml ו-media_codecs.xml למיקום המתאים, מוסיפים את השורות הבאות לקובץ ה-makefile של המכשיר:device/<company_name>/<device_name>/device.mk
    # 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 בקובץ device/<company>/<device>/device.mk makefile של המכשיר:
    PRODUCT_PACKAGES := \
    Gallery2 \
    ...