พัฒนารหัสเคอร์เนลสำหรับ GKI

Generic Kernel Image (GKI) ช่วยลดการกระจายตัวของเคอร์เนลโดยการจัดตำแหน่งอย่างใกล้ชิดกับเคอร์เนล Linux อัปสตรีม อย่างไรก็ตาม มีสาเหตุที่ถูกต้องว่าทำไมจึงไม่ยอมรับแพตช์บางตัวในต้นทาง และมีกำหนดการของผลิตภัณฑ์ที่ต้องปฏิบัติตาม ดังนั้นแพตช์บางรายการจึงได้รับการบำรุงรักษาในแหล่งที่มาของ Android Common Kernel (ACK) ที่ใช้สร้าง GKI

นักพัฒนาจะต้องส่งการเปลี่ยนแปลงโค้ดอัปสตรีมโดยใช้ Linux Kernel Mailing List (LKML) เป็นตัวเลือกแรก และส่งการเปลี่ยนแปลงโค้ดไปยังสาขา android-mainline ACK เฉพาะเมื่อมีเหตุผลที่ชัดเจนว่าทำไมอัปสตรีมไม่สามารถใช้งานได้ ตัวอย่างของเหตุผลที่ถูกต้องและวิธีการจัดการมีดังต่อไปนี้

  • โปรแกรมแก้ไขถูกส่งไปยัง LKML แต่ไม่ได้รับการยอมรับทันเวลาสำหรับการเปิดตัวผลิตภัณฑ์ วิธีจัดการกับแพตช์นี้:

    • แสดงหลักฐานว่าได้ส่งโปรแกรมแก้ไขไปยัง LKML และความคิดเห็นที่ได้รับสำหรับโปรแกรมแก้ไข หรือเวลาโดยประมาณที่โปรแกรมแก้ไขจะถูกส่งต้นทาง
    • ตัดสินใจเลือกแนวทางดำเนินการเพื่อนำแพตช์ลง ACK ให้ได้รับการอนุมัติอัปสตรีม จากนั้นนำออกจาก ACK เมื่อเวอร์ชันอัปสตรีมสุดท้ายถูกรวมเข้ากับ ACK
  • โปรแกรมแก้ไขกำหนด EXPORT_SYMBOLS_GPL() สำหรับโมดูลผู้ขาย แต่ไม่สามารถส่งอัปสตรีมได้เนื่องจากไม่มีโมดูลในแผนผังที่ใช้สัญลักษณ์นั้น ในการจัดการกับแพตช์นี้ โปรดระบุรายละเอียดว่าทำไมโมดูลของคุณจึงไม่สามารถส่งอัปสตรีมได้ และทางเลือกอื่นที่คุณพิจารณาก่อนที่จะส่งคำขอนี้

  • แพตช์นี้ไม่ทั่วถึงเพียงพอสำหรับอัพสตรีม และไม่มีเวลาที่จะปรับโครงสร้างใหม่ก่อนที่จะออกผลิตภัณฑ์ ในการจัดการแพตช์นี้ ให้ระบุเวลาโดยประมาณที่แพตช์ที่ปรับโครงสร้างใหม่จะถูกส่งต้นทาง (แพตช์จะไม่ได้รับการยอมรับใน ACK หากไม่มีแผนที่จะส่งแพตช์ที่ปรับโครงสร้างใหม่ต้นทางเพื่อรับการตรวจทาน)

  • อัพสตรีมไม่สามารถยอมรับแพตช์ได้เนื่องจาก... <ใส่เหตุผลที่นี่> ในการจัดการกับแพตช์นี้ โปรดติดต่อทีมเคอร์เนล Android และทำงานร่วมกับเราเกี่ยวกับตัวเลือกต่างๆ ในการปรับโครงสร้างแพตช์ใหม่ เพื่อให้สามารถส่งเข้ารับการตรวจสอบและยอมรับอัปสตรีมได้

มีเหตุผลที่เป็นไปได้อีกมากมาย เมื่อคุณส่งจุดบกพร่องหรือแพทช์ของคุณ ให้ระบุเหตุผลที่ถูกต้องและคาดว่าจะมีการทำซ้ำและการอภิปราย เราตระหนักดีว่า ACK จะมีแพตช์บางส่วน โดยเฉพาะอย่างยิ่งในช่วงแรกของ GKI ในขณะที่ทุกคนกำลังเรียนรู้วิธีการทำงานต้นน้ำ แต่ไม่สามารถผ่อนปรนกำหนดการของผลิตภัณฑ์ให้ทำเช่นนั้นได้ คาดว่าข้อกำหนดการอัปสตรีมจะเข้มงวดมากขึ้นเมื่อเวลาผ่านไป

ข้อกำหนดของแพทช์

แพตช์ต้องเป็นไปตามมาตรฐานการเข้ารหัสเคอร์เนล Linux ที่อธิบายไว้ใน แผนผังต้นทางของ Linux ไม่ว่าจะส่งอัปสตรีมหรือส่งไปยัง ACK ก็ตาม สคริปต์ scripts/checkpatch.pl ทำงานเป็นส่วนหนึ่งของการทดสอบส่งล่วงหน้าของ Gerrit ดังนั้นให้รันสคริปต์ล่วงหน้าเพื่อให้แน่ใจว่าผ่าน หากต้องการรันสคริปต์ checkpatch ด้วยการกำหนดค่าเดียวกันกับการทดสอบก่อนส่ง ให้ใช้ //build/kernel/static_analysis:checkpatch_presubmit สำหรับรายละเอียด โปรดดูที่ build/kernel/kleaf/docs/checkpatch.md

ACK แพตช์

แพตช์ที่ส่งไปยัง ACK จะต้องเป็นไปตามมาตรฐานการเข้ารหัสเคอร์เนล Linux และ แนวทางการสนับสนุน คุณต้องรวมแท็ก Change-Id ไว้ในข้อความยืนยัน หากคุณส่งแพตช์ไปยังหลายสาขา (เช่น android-mainline และ android12-5.4 ) คุณต้องใช้ Change-Id เดียวกันสำหรับอินสแตนซ์ทั้งหมดของแพตช์

ส่งแพตช์ไปที่ LKML ก่อนเพื่อรับการตรวจสอบอัปสตรีม หากแพทช์คือ:

  • ยอมรับต้นน้ำ โดยจะรวมเข้ากับ android-mainline โดยอัตโนมัติ
  • ไม่ยอมรับอัปสตรีม ให้ส่งไปที่ android-mainline โดยมีการอ้างอิงถึงการส่งอัปสตรีมหรือคำอธิบายว่าทำไมจึงไม่ส่งไปที่ LKML

หลังจากยอมรับแพตช์อัปสตรีมหรือใน android-mainline แล้ว ก็สามารถแบ็กพอร์ตไปยัง ACK ที่ใช้ LTS ที่เหมาะสมได้ (เช่น android12-5.4 และ android11-5.4 สำหรับแพตช์ที่แก้ไขโค้ดเฉพาะของ Android) การส่งไปยัง android-mainline ช่วยให้สามารถทดสอบกับผู้สมัครอัปสตรีมรีลีสใหม่และรับประกันว่าแพตช์จะอยู่ใน ACK ที่ใช้ LTS ถัดไป ข้อยกเว้นรวมถึงกรณีที่แพตช์อัปสตรีมถูกแบ็คพอร์ตไปยัง android12-5.4 (เนื่องจากแพตช์มีแนวโน้มที่จะอยู่ใน android-mainline อยู่แล้ว)

แพทช์ต้นน้ำ

ตามที่ระบุไว้ใน แนวทางการสนับสนุน แพตช์อัปสตรีมที่กำหนดไว้สำหรับเคอร์เนล ACK จะจัดอยู่ในกลุ่มต่อไปนี้ (แสดงรายการตามลำดับความเป็นไปได้ที่จะได้รับการยอมรับ)

  • UPSTREAM: - แพตช์ที่เชอร์รี่เลือกจาก 'android-mainline` มีแนวโน้มที่จะได้รับการยอมรับใน ACK หากมีกรณีการใช้งานที่สมเหตุสมผล
  • BACKPORT: - แพตช์จากอัปสตรีมที่ไม่ได้เก็บเชอร์รี่อย่างหมดจดและจำเป็นต้องมีการดัดแปลงก็มีแนวโน้มที่จะได้รับการยอมรับหากมีกรณีการใช้งานที่สมเหตุสมผล
  • FROMGIT: - แพตช์ที่เชอร์รี่เลือกจากสาขาผู้ดูแลเพื่อเตรียมส่งไปยัง Linux mainline อาจได้รับการยอมรับหากมีกำหนดเวลาที่กำลังจะมาถึง สิ่งเหล่านี้จะต้องสมเหตุสมผลทั้งสำหรับเนื้อหาและกำหนดการ
  • FROMLIST: - แพตช์ที่ส่งไปยัง LKML แต่ยังไม่ได้รับการยอมรับในสาขาผู้ดูแล แต่ก็ไม่น่าจะได้รับการยอมรับ เว้นแต่การให้เหตุผลนั้นน่าสนใจเพียงพอที่แพตช์จะได้รับการยอมรับไม่ว่าจะลงจอดใน Linux อัปสตรีมหรือไม่ (เราถือว่า ว่าจะไม่) ต้องมีปัญหาที่เกี่ยวข้องกับแพตช์ FROMLIST เพื่ออำนวยความสะดวกในการหารือกับทีมเคอร์เนล Android

แพทช์เฉพาะสำหรับ Android

หากคุณไม่สามารถดำเนินการเปลี่ยนแปลงที่จำเป็นได้ที่ต้นทาง คุณสามารถลองส่งแพตช์นอกแผนผังไปที่ ACK ได้โดยตรง การส่งแพตช์ที่ไม่อยู่ในลำดับต้นๆ คุณต้องสร้างปัญหาในฝ่ายไอทีที่อ้างอิงแพตช์และเหตุผลว่าเหตุใดจึงไม่สามารถส่งแพตช์อัปสตรีมได้ (ดูตัวอย่างในรายการก่อนหน้า) อย่างไรก็ตาม มีบางกรณีที่ไม่สามารถส่งรหัสต้นทางได้ กรณีเหล่านี้ครอบคลุมดังต่อไปนี้ และต้องเป็นไปตาม หลักเกณฑ์การสนับสนุน สำหรับแพตช์เฉพาะของ Android และติดแท็กด้วยคำนำหน้า ANDROID: ในหัวเรื่อง

เปลี่ยนเป็น gki_defconfig

การเปลี่ยนแปลง CONFIG ทั้งหมดใน gki_defconfig จะต้องนำไปใช้กับทั้งเวอร์ชัน arm64 และ x86 เว้นแต่ว่า CONFIG จะเป็นสถาปัตยกรรมเฉพาะ หากต้องการขอเปลี่ยนแปลงการตั้งค่า CONFIG ให้สร้างปัญหาในฝ่ายไอทีเพื่อหารือเกี่ยวกับการเปลี่ยนแปลง การเปลี่ยนแปลง CONFIG ใดๆ ที่ส่งผลต่อ Kernel Module Interface (KMI) หลังจากที่ถูกแช่แข็งจะถูกปฏิเสธ ในกรณีที่พันธมิตรร้องขอการตั้งค่าที่ขัดแย้งกันสำหรับการกำหนดค่าเดียว เราจะแก้ไขข้อขัดแย้งผ่านการหารือเกี่ยวกับจุดบกพร่องที่เกี่ยวข้อง

รหัสที่ไม่มีต้นน้ำ

การแก้ไขโค้ดที่เป็นเฉพาะของ Android อยู่แล้วไม่สามารถส่งอัปสตรีมได้ ตัวอย่างเช่น แม้ว่าไดรเวอร์ Binder จะได้รับการดูแลต้นทาง แต่การแก้ไขคุณลักษณะการสืบทอดลำดับความสำคัญของไดรเวอร์ Binder จะไม่สามารถส่งต้นทางได้ เนื่องจากเป็นคุณลักษณะเฉพาะของ Android ระบุข้อบกพร่องให้ชัดเจนและแก้ไขสาเหตุที่ไม่สามารถส่งโค้ดอัปสตรีมได้ หากเป็นไปได้ ให้แยกแพตช์ออกเป็นส่วนๆ ที่สามารถส่งอัปสตรีมได้ และส่วนเฉพาะของ Android ที่ไม่สามารถส่งอัปสตรีมได้ เพื่อลดจำนวนโค้ดที่ไม่อยู่ในแผนผังที่เก็บรักษาไว้ใน ACK

การเปลี่ยนแปลงอื่นๆ ในหมวดหมู่นี้คือการอัปเดตไฟล์การแสดง KMI รายการสัญลักษณ์ KMI gki_defconfig สคริปต์บิวด์หรือการกำหนดค่า หรือสคริปต์อื่นๆ ที่ไม่มีต้นทาง

โมดูลนอกแผนผัง

Upstream Linux ไม่สนับสนุนการสร้างโมดูลนอกแผนผังอย่างจริงจัง นี่เป็นตำแหน่งที่สมเหตุสมผล เนื่องจากผู้ดูแล Linux ไม่รับประกันเกี่ยวกับซอร์สในเคอร์เนลหรือความเข้ากันได้ของไบนารี และไม่ต้องการรองรับโค้ดที่ไม่ได้อยู่ในแผนผัง อย่างไรก็ตาม GKI ให้ การรับประกัน ABI สำหรับโมดูลของผู้จำหน่าย เพื่อให้มั่นใจว่าอินเทอร์เฟซ KMI มีความเสถียรตลอดอายุการใช้งานของเคอร์เนลที่รองรับ ดังนั้นจึงมีการเปลี่ยนแปลงระดับหนึ่งเพื่อสนับสนุนโมดูลของผู้จัดจำหน่ายที่ยอมรับได้สำหรับ ACK แต่ไม่ยอมรับสำหรับอัปสตรีม

ตัวอย่างเช่น พิจารณาแพตช์ที่เพิ่มมาโคร EXPORT_SYMBOL_GPL() โดยที่โมดูลที่ใช้การส่งออกไม่อยู่ในแผนผังต้นทาง แม้ว่าคุณจะต้องพยายามขอ EXPORT_SYMBOL_GPL() อัปสตรีมและจัดหาโมดูลที่ใช้สัญลักษณ์ที่ส่งออกใหม่ หากมีเหตุผลที่ถูกต้องว่าทำไมโมดูลจึงไม่ถูกส่งอัปสตรีม คุณสามารถส่งโปรแกรมแก้ไขไปที่ ACK แทนได้ คุณต้องระบุเหตุผลว่าเหตุใดโมดูลจึงไม่สามารถอัปสตรีมในปัญหาได้ (อย่าขอตัวแปรที่ไม่ใช่ GPL EXPORT_SYMBOL() .)

การกำหนดค่าที่ซ่อนอยู่

โมดูลในแผนผังบางโมดูลจะเลือกการกำหนดค่าที่ซ่อนอยู่ซึ่งไม่สามารถระบุใน gki_defconfig ได้โดยอัตโนมัติ ตัวอย่างเช่น CONFIG_SND_SOC_TOPOLOGY จะถูกเลือกโดยอัตโนมัติเมื่อมีการกำหนดค่า CONFIG_SND_SOC_SOF=y เพื่อรองรับการสร้างโมดูลนอกแผนผัง GKI มีกลไกในการเปิดใช้งานการกำหนดค่าที่ซ่อนอยู่

หากต้องการเปิดใช้งานการกำหนดค่าที่ซ่อนอยู่ ให้เพิ่มคำสั่ง select ใน init/Kconfig.gki เพื่อให้ระบบเลือกโดยอัตโนมัติตามการกำหนดค่าเคอร์เนล CONFIG_GKI_HACKS_TO_FIX ซึ่งเปิดใช้งานใน gki_defconfig ใช้กลไกนี้สำหรับการกำหนดค่าที่ซ่อนอยู่เท่านั้น หากไม่ได้ซ่อนการกำหนดค่าไว้ จะต้องระบุการกำหนดค่านั้นใน gki_defconfig อย่างชัดเจนหรือเป็นการขึ้นต่อกัน

ผู้ว่าราชการโหลดได้

สำหรับเฟรมเวิร์กเคอร์เนล (เช่น cpufreq ) ที่รองรับ Governor ที่โหลดได้ คุณสามารถแทนที่ Governor ที่เป็นค่าเริ่มต้นได้ (เช่น schedutil Governor ของ cpufreq สำหรับเฟรมเวิร์ก (เช่น กรอบงานระบายความร้อน) ที่ไม่รองรับ Governor หรือไดรเวอร์ที่โหลดได้ แต่ยังต้องการ การใช้งานเฉพาะผู้ขาย สร้างปัญหาในด้านไอทีและปรึกษากับ ทีมเคอร์เนล Android

เราจะทำงานร่วมกับคุณและผู้ดูแลต้นน้ำเพื่อเพิ่มการสนับสนุนที่จำเป็น

ตะขอผู้ขาย

ในรีลีสที่ผ่านมา คุณสามารถเพิ่มการแก้ไขเฉพาะผู้จำหน่ายลงในเคอร์เนลหลักได้โดยตรง สิ่งนี้เป็นไปไม่ได้กับ GKI 2.0 เนื่องจากต้องใช้รหัสเฉพาะผลิตภัณฑ์ในโมดูล และจะไม่ได้รับการยอมรับในเคอร์เนลหลักต้นทางหรือใน ACK เพื่อเปิดใช้งานคุณสมบัติเพิ่มมูลค่าที่พันธมิตรพึ่งพาโดยมีผลกระทบน้อยที่สุดต่อโค้ดเคอร์เนลหลัก GKI ยอมรับ hooks ของผู้จำหน่ายที่อนุญาตให้เรียกใช้โมดูลจากโค้ดเคอร์เนลหลักได้ นอกจากนี้ โครงสร้างข้อมูลที่สำคัญสามารถเสริมด้วยฟิลด์ข้อมูลผู้ขายที่พร้อมใช้งานเพื่อจัดเก็บข้อมูลเฉพาะของผู้ขายเพื่อใช้คุณลักษณะเหล่านี้

Hook ของผู้จัดจำหน่ายมีสองรูปแบบ (ปกติและแบบจำกัด) ซึ่งขึ้นอยู่กับจุดติดตาม (ไม่ใช่การติดตามเหตุการณ์) ที่โมดูลผู้จัดจำหน่ายสามารถแนบได้ ตัวอย่างเช่น แทนที่จะเพิ่มฟังก์ชัน sched_exit() ใหม่เพื่อทำการบัญชีเมื่อออกจากงาน ผู้ขายสามารถเพิ่ม hook ใน do_exit() ที่โมดูลผู้ขายสามารถแนบไปกับการประมวลผลได้ การใช้งานตัวอย่างรวมถึง hooks ของผู้ขายต่อไปนี้

  • hook ของผู้ขายปกติใช้ DECLARE_HOOK() เพื่อสร้างฟังก์ชันจุดติดตามด้วยชื่อ trace_ name โดยที่ name เป็นตัวระบุที่ไม่ซ้ำกันสำหรับการติดตาม ตามธรรมเนียมแล้ว ชื่อ vendor hook ปกติจะขึ้นต้นด้วย android_vh ดังนั้นชื่อของ sched_exit() hook จะเป็น android_vh_sched_exit
  • hook ของผู้จำหน่ายแบบจำกัดเป็นสิ่งจำเป็นสำหรับกรณีต่างๆ เช่น hooks ของตัวกำหนดเวลาซึ่งจะต้องเรียกใช้ฟังก์ชันที่แนบมาแม้ว่า CPU จะออฟไลน์หรือต้องการบริบทที่ไม่ใช่อะตอมมิกก็ตาม hook ของผู้ขายแบบจำกัดไม่สามารถถอดออกได้ ดังนั้นโมดูลที่ต่อกับ hook แบบจำกัดจะไม่สามารถยกเลิกการโหลดได้ ชื่อ hook ของผู้จำหน่ายที่ถูกจำกัดขึ้นต้นด้วย android_rvh

หากต้องการเพิ่ม vendor hook ให้ยื่นปัญหาในฝ่ายไอทีและส่งแพตช์ (เช่นเดียวกับแพตช์เฉพาะ Android ทั้งหมด จะต้องมีปัญหาอยู่และคุณต้องระบุเหตุผล) การสนับสนุน hooks ของผู้ขายมีอยู่ใน ACK เท่านั้น ดังนั้นอย่าส่งแพตช์เหล่านี้ไปยัง Linux อัปสตรีม

เพิ่มฟิลด์ผู้ขายให้กับโครงสร้าง

คุณสามารถเชื่อมโยงข้อมูลผู้ขายกับโครงสร้างข้อมูลหลักได้โดยการเพิ่มช่อง android_vendor_data โดยใช้มาโคร ANDROID_VENDOR_DATA() ตัวอย่างเช่น เพื่อสนับสนุนคุณลักษณะที่มีมูลค่าเพิ่ม ให้ผนวกเขตข้อมูลเข้ากับโครงสร้างตามที่แสดงในตัวอย่างโค้ดต่อไปนี้

เพื่อหลีกเลี่ยงความขัดแย้งที่อาจเกิดขึ้นระหว่างฟิลด์ที่ผู้ขายต้องการและฟิลด์ที่ OEM ต้องการ OEM จะต้องไม่ใช้ฟิลด์ที่ประกาศโดยใช้มาโคร ANDROID_VENDOR_DATA() OEM จะต้องใช้ ANDROID_OEM_DATA() เพื่อประกาศช่อง android_oem_data แทน

#include <linux/android_vendor.h>
...
struct important_kernel_data {
  [all the standard fields];
  /* Create vendor data for use by hook implementations. The
   * size of vendor data is based on vendor input. Vendor data
   * can be defined as single u64 fields like the following that
   * declares a single u64 field named "android_vendor_data1" :
   */
  ANDROID_VENDOR_DATA(1);

  /*
   * ...or an array can be declared. The following is equivalent to
   * u64 android_vendor_data2[20]:
   */
  ANDROID_VENDOR_DATA_ARRAY(2, 20);

  /*
   * SoC vendors must not use fields declared for OEMs and
   * OEMs must not use fields declared for SoC vendors.
   */
  ANDROID_OEM_DATA(1);

  /* no further fields */
}

กำหนด hooks ของผู้ขาย

เพิ่ม vendor hooks ให้กับโค้ดเคอร์เนลเป็นจุดติดตามโดยการประกาศโดยใช้ DECLARE_HOOK() หรือ DECLARE_RESTRICTED_HOOK() จากนั้นเพิ่มลงในโค้ดเป็นจุดติดตาม ตัวอย่างเช่น หากต้องการเพิ่ม trace_android_vh_sched_exit() ให้กับฟังก์ชันเคอร์เนล do_exit() ที่มีอยู่:

#include <trace/hooks/exit.h>
void do_exit(long code)
{
    struct task_struct *tsk = current;
    ...
    trace_android_vh_sched_exit(tsk);
    ...
}

ฟังก์ชัน trace_android_vh_sched_exit() จะตรวจสอบในขั้นต้นเมื่อมีบางสิ่งแนบอยู่เท่านั้น อย่างไรก็ตาม หากโมดูลผู้จำหน่ายลงทะเบียนตัวจัดการโดยใช้ register_trace_android_vh_sched_exit() ฟังก์ชันที่ลงทะเบียนไว้จะถูกเรียกใช้ ตัวจัดการจะต้องทราบถึงบริบทที่เกี่ยวข้องกับการล็อคที่ถูกระงับ สถานะ RCS และปัจจัยอื่นๆ hook ต้องถูกกำหนดไว้ในไฟล์ส่วนหัวในไดเร็กทอรี include/trace/hooks

ตัวอย่างเช่น โค้ดต่อไปนี้ให้การประกาศที่เป็นไปได้สำหรับ trace_android_vh_sched_exit() ในไฟล์ include/trace/hooks/exit.h

/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM sched
#define TRACE_INCLUDE_PATH trace/hooks

#if !defined(_TRACE_HOOK_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_HOOK_SCHED_H
#include <trace/hooks/vendor_hooks.h>
/*
 * Following tracepoints are not exported in tracefs and provide a
 * mechanism for vendor modules to hook and extend functionality
 */

struct task_struct;

DECLARE_HOOK(android_vh_sched_exit,
             TP_PROTO(struct task_struct *p),
             TP_ARGS(p));

#endif /* _TRACE_HOOK_SCHED_H */

/* This part must be outside protection */
#include <trace/define_trace.h>

หากต้องการสร้างอินสแตนซ์อินเทอร์เฟซที่จำเป็นสำหรับ vendor hook ให้เพิ่มไฟล์ส่วนหัวพร้อมกับการประกาศ hook ไปยัง drivers/android/vendor_hooks.c และส่งออกสัญลักษณ์ ตัวอย่างเช่น โค้ดต่อไปนี้ทำให้การประกาศของ hook android_vh_sched_exit() เสร็จสมบูรณ์

#ifndef __GENKSYMS__
/* struct task_struct */
#include <linux/sched.h>
#endif

#define CREATE_TRACE_POINTS
#include <trace/hooks/vendor_hooks.h>
#include <trace/hooks/exit.h>
/*
 * Export tracepoints that act as a bare tracehook (i.e. have no trace
 * event associated with them) to allow external modules to probe
 * them.
 */
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sched_exit);

หมายเหตุ : โครงสร้างข้อมูลที่ใช้ภายในการประกาศ hook จำเป็นต้องได้รับการกำหนดอย่างสมบูรณ์เพื่อรับประกันความเสถียรของ ABI มิฉะนั้นจะไม่ปลอดภัยที่จะอ้างอิงพอยน์เตอร์ทึบแสงหรือใช้โครงสร้างในบริบทที่มีขนาด การ include ซึ่งให้คำจำกัดความแบบเต็มของโครงสร้างข้อมูลดังกล่าวควรอยู่ภายในส่วน #ifndef __GENKSYMS__ ของ drivers/android/vendor_hooks.c ไฟล์ส่วนหัวใน include/trace/hooks ไม่ควรรวมไฟล์ส่วนหัวเคอร์เนลที่มีคำจำกัดความประเภท เพื่อหลีกเลี่ยงการเปลี่ยนแปลง CRC ซึ่งจะทำให้ KMI เสียหาย แทนที่จะส่งต่อประกาศประเภท

ติดเข้ากับตะขอของผู้ขาย

หากต้องการใช้ hooks ของผู้ขาย โมดูลผู้ขายจำเป็นต้องลงทะเบียนตัวจัดการสำหรับ hook (โดยทั่วไปจะทำระหว่างการเริ่มต้นโมดูล) ตัวอย่างเช่น โค้ดต่อไปนี้แสดงโมดูล foo.ko handler สำหรับ trace_android_vh_sched_exit()

#include <trace/hooks/sched.h>
...
static void foo_sched_exit_handler(void *data, struct task_struct *p)
{
    foo_do_exit_accounting(p);
}
...
static int foo_probe(..)
{
    ...
    rc = register_trace_android_vh_sched_exit(foo_sched_exit_handler, NULL);
    ...
}

คุณสมบัติเคอร์เนลหลัก

หากไม่มีเทคนิคก่อนหน้านี้ที่ทำให้คุณสามารถใช้คุณลักษณะจากโมดูลได้ คุณจะต้องเพิ่มคุณลักษณะดังกล่าวเป็นการดัดแปลงเฉพาะของ Android ให้กับเคอร์เนลหลัก สร้างปัญหาในตัวติดตามปัญหา (IT) เพื่อเริ่มการสนทนา

ส่วนต่อประสานการเขียนโปรแกรมแอปพลิเคชันผู้ใช้ (UAPI)

  • ไฟล์ส่วนหัว UAPI การเปลี่ยนแปลง ไฟล์ส่วนหัว UAPI จะต้องเกิดขึ้นที่ต้นทาง เว้นแต่การเปลี่ยนแปลงนั้นเกิดขึ้นกับอินเทอร์เฟซเฉพาะของ Android ใช้ไฟล์ส่วนหัวเฉพาะของผู้จำหน่ายเพื่อกำหนดอินเทอร์เฟซระหว่างโมดูลของผู้จำหน่ายและรหัสพื้นที่ผู้ใช้ของผู้จำหน่าย
  • โหนด sysfs อย่าเพิ่มโหนด sysfs ใหม่ให้กับเคอร์เนล GKI (การเพิ่มดังกล่าวใช้ได้เฉพาะในโมดูลของผู้ขายเท่านั้น) โหนด sysfs ที่ใช้โดย SoC- และไลบรารีที่ไม่เชื่อเรื่องอุปกรณ์และโค้ด Java ที่ประกอบด้วยเฟรมเวิร์ก Android สามารถเปลี่ยนแปลงได้ในวิธีที่เข้ากันได้เท่านั้น และจะต้องเปลี่ยนอัปสตรีมหากไม่ใช่โหนด sysfs เฉพาะของ Android คุณ สามารถ สร้างโหนด sysfs เฉพาะผู้จำหน่ายเพื่อใช้โดยพื้นที่ผู้ใช้ของผู้จำหน่าย ตามค่าเริ่มต้น การเข้าถึงโหนด sysfs โดยพื้นที่ผู้ใช้จะถูกปฏิเสธโดยใช้ SELinux ขึ้นอยู่กับผู้จำหน่ายที่จะเพิ่มป้ายกำกับ SELinux ที่เหมาะสมเพื่ออนุญาตการเข้าถึงโดยซอฟต์แวร์ของผู้จำหน่ายที่ได้รับอนุญาต
  • โหนด DebugFS โมดูลผู้จำหน่ายสามารถกำหนดโหนดใน debugfs สำหรับการดีบักเท่านั้น (เนื่องจาก debugfs ไม่ได้ถูกเมาท์ระหว่างการทำงานปกติของอุปกรณ์)