מצלמה

סמל של 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. הקוד שנוצר קורא לקוד המקורי ברמה הנמוכה כדי לקבל גישה למצלמה הפיזית, ומחזיר נתונים שמשמשים ליצירת האובייקטים CameraDevice ובסופו של דבר CameraCaptureSession ברמת המסגרת.
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, שמתואר למעלה.

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

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

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

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

app framework
ברמת מסגרת האפליקציה נמצא הקוד של האפליקציה, שמשתמש ב-API‏ android.hardware.Camera כדי ליצור אינטראקציה עם חומרת המצלמה. באופן פנימי, הקוד הזה קורא למחלקת דבק JNI תואמת כדי לגשת לקוד ה-Native שמתקשר עם המצלמה.
JNI
קוד ה-JNI שמשויך ל- android.hardware.Camera נמצא ב-frameworks/base/core/jni/android_hardware_Camera.cpp. הקוד הזה קורא לקוד המקורי ברמה הנמוכה כדי לקבל גישה למצלמה הפיזית ומחזיר נתונים שמשמשים ליצירת האובייקט android.hardware.Camera ברמת המסגרת.
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 מכיל קוד שמתאים ל- 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 של המכשיר:
    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. פרטים נוספים זמינים במאמר בנושא חשיפת רכיבי codec למסגרת.
  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 \
    ...