उपयोगकर्ता के डेटा का चेकपॉइंट

Android 10 में यूज़र डेटा चेकपॉइंट (यूडीसी) की सुविधा जोड़ी गई है. इससे, Android ओवर-द-एयर (ओटीए) अपडेट पूरा न होने पर, Android को उसकी पिछली स्थिति पर वापस लाया जा सकता है. यूडीसी की मदद से, अगर Android ओटीए अपडेट पूरा नहीं हो पाता है, तो डिवाइस को सुरक्षित तरीके से उसकी पिछली स्थिति पर वापस लाया जा सकता है. हालांकि, A/B अपडेट, जल्दी बूट होने की इस समस्या को हल करते हैं. हालांकि, उपयोगकर्ता के डेटा सेक्शन (/data पर माउंट किया गया) में बदलाव होने पर, रोलबैक की सुविधा काम नहीं करती.

यूडीसी की मदद से, डिवाइस में उपयोगकर्ता के डेटा के लिए बने partition में बदलाव करने के बाद भी, उसे पहले जैसा किया जा सकता है. यूडीसी की सुविधा, फ़ाइल सिस्टम में चेकपॉइंट की सुविधाओं की मदद से ऐसा करती है. यह सुविधा, फ़ाइल सिस्टम में चेकपॉइंट की सुविधा न होने पर, एक वैकल्पिक तरीके के तौर पर काम करती है. साथ ही, यह बूटलोडर के A/B सिस्टम के साथ इंटिग्रेट होती है. हालांकि, यह A/B के अलावा अन्य अपडेट के साथ भी काम करती है. साथ ही, यह पासकोड के वर्शन को बांधने और पासकोड को रोलबैक होने से रोकने की सुविधा के साथ भी काम करती है.

उपयोगकर्ता पर असर

यूडीसी की सुविधा से, उपयोगकर्ताओं के लिए ओटीए अपडेट का अनुभव बेहतर हो जाता है. ऐसा इसलिए, क्योंकि ओटीए अपडेट पूरा न होने पर, कम उपयोगकर्ताओं का डेटा मिटता है. इससे, अपडेट की प्रोसेस के दौरान समस्याओं का सामना करने वाले उपयोगकर्ताओं की सहायता टीम को किए जाने वाले कॉल की संख्या कम हो सकती है. हालांकि, ओटीए अपडेट न होने पर, उपयोगकर्ताओं को डिवाइस कई बार रीबूट होते हुए दिख सकता है.

यह कैसे काम करता है

अलग-अलग फ़ाइल सिस्टम में चेकपॉइंट की सुविधा

F2FS फ़ाइल सिस्टम के लिए, UDC, अपस्ट्रीम 4.20 Linux कर्नेल में चेकपॉइंट की सुविधा जोड़ता है. साथ ही, इसे Android 10 पर काम करने वाले डिवाइसों के साथ काम करने वाले सभी सामान्य कर्नेल में बैकपोर्ट करता है.

अन्य फ़ाइल सिस्टम के लिए, यूडीसी, चेकपॉइंट की सुविधा के लिए, dm_bow नाम के डिवाइस मैपर वर्चुअल डिवाइस का इस्तेमाल करता है. dm_bow, डिवाइस और फ़ाइल सिस्टम के बीच में होता है. जब कोई पार्टीशन माउंट किया जाता है, तो ट्रिम जारी किया जाता है. इससे फ़ाइल सिस्टम, सभी खाली ब्लॉक पर ट्रिम कमांड जारी करता है. dm_bow इन ट्रिम को इंटरसेप्ट करता है और उनका इस्तेमाल करके, मुफ़्त ब्लॉक सूची सेट अप करता है. इसके बाद, डेटा को बिना किसी बदलाव के डिवाइस पर भेजा जाता है. हालांकि, डेटा को लिखने की अनुमति देने से पहले, डेटा को वापस लाने के लिए ज़रूरी डेटा को किसी खाली ब्लॉक में बैक अप ले लिया जाता है.

चेकपॉइंट की प्रोसेस

जब checkpoint=fs/block फ़्लैग वाला कोई पार्टीशन माउंट किया जाता है, तो Android, डिवाइस को किसी भी मौजूदा चेकपॉइंट को वापस लाने की अनुमति देने के लिए, Drive पर restoreCheckpoint को कॉल करता है. इसके बाद, init, needsCheckpoint फ़ंक्शन को कॉल करता है, ताकि यह पता लगाया जा सके कि डिवाइस, बूटलोडर A/B स्टेटस में है या अपडेट को फिर से कोशिश करने की संख्या सेट की गई है. अगर इनमें से कोई भी वैल्यू 'सही है' पर सेट है, तो Android, माउंट फ़्लैग जोड़ने या dm_bow डिवाइस बनाने के लिए createCheckpoint को कॉल करता है.

पार्टीशन को माउंट करने के बाद, ट्रिम करने के लिए चेकपॉइंट कोड को कॉल किया जाता है. इसके बाद, बूट प्रोसेस सामान्य तरीके से जारी रहती है. LOCKED_BOOT_COMPLETE पर, Android, मौजूदा चेकपॉइंट को कमिट करने के लिए commitCheckpoint को कॉल करता है और अपडेट सामान्य तरीके से जारी रहता है.

KeyMint (पहले इसे Keymaster कहा जाता था) की कुंजियां मैनेज करना

KeyMint पासकोड का इस्तेमाल, डिवाइस को एन्क्रिप्ट करने या अन्य कामों के लिए किया जाता है. इन बटन को मैनेज करने के लिए, Android, चेकपॉइंट के कमिट होने तक, बटन मिटाने के अनुरोधों को रोक देता है.

सेहत की निगरानी करना

हेल्थ डेमन यह पुष्टि करता है कि चेकपॉइंट बनाने के लिए, डिस्क में ज़रूरत के मुताबिक जगह है या नहीं. हेल्थ डेमन, Checkpoint.cpp में cp_healthDaemon में मौजूद होता है.

हेल्थ डेमन के ये काम कॉन्फ़िगर किए जा सकते हैं:

  • ro.sys.cp_msleeptime: यह कंट्रोल करता है कि डिवाइस, डिस्क के इस्तेमाल की जांच कितनी बार करता है.
  • ro.sys.cp_min_free_bytes: यह उस कम से कम वैल्यू को कंट्रोल करता है जिसे हेल्थ डेमन खोजता है.
  • ro.sys.cp_commit_on_full: इससे यह कंट्रोल होता है कि डिवाइस को फिर से चालू करने के लिए, हेल्थ डेमन क्या करता है. इसके अलावा, यह भी कंट्रोल करता है कि डिस्क भर जाने पर, वह चेकपॉइंट को सेव करके प्रोसेस जारी रखता है या नहीं.

Checkpoint APIs

चेकपॉइंट एपीआई का इस्तेमाल, यूडीसी सुविधा करती है. यूडीसी के ज़रिए इस्तेमाल किए जाने वाले अन्य एपीआई के बारे में जानने के लिए, IVold.aidl देखें.

void startCheckpoint(int retry)

चेकपॉइंट बनाता है.

अपडेट शुरू करने के लिए तैयार होने पर, फ़्रेमवर्क इस तरीके को कॉल करता है. रीबूट के बाद, userdata जैसे चेकपॉइंट किए गए फ़ाइल सिस्टम को फिर से पढ़ने और लिखने के लिए माउंट करने से पहले, चेकपॉइंट बनाया जाता है. अगर फिर से कोशिश करने की संख्या ज़्यादा है, तो एपीआई, फिर से कोशिश करने की प्रोसेस को मैनेज करता है. साथ ही, अपडेटर needsRollback को कॉल करता है, ताकि यह पता लगाया जा सके कि अपडेट को रोलबैक करना ज़रूरी है या नहीं. अगर फिर से कोशिश करने की संख्या -1 है, तो एपीआई A/B bootloader के फ़ैसले पर निर्भर करता है.

सामान्य A/B अपडेट करते समय, इस तरीके को नहीं बुलाया जाता.

void commitChanges()

बदलावों को लागू करता है.

फ़्रेमवर्क, रीबूट के बाद इस तरीके को कॉल करता है, जब बदलाव लागू करने के लिए तैयार हों. डेटा (जैसे कि फ़ोटो, वीडियो, एसएमएस, रिसीव किए जाने की जानकारी) को उपयोगकर्ता डेटा में लिखने से पहले और BootComplete से पहले, इसे कॉल किया जाता है.

अगर कोई चालू चेकपॉइंट अपडेट मौजूद नहीं है, तो इस तरीके का कोई असर नहीं पड़ेगा.

abortChanges()

डिवाइस को रीबूट करता है और उसे चेकपॉइंट पर वापस ले जाता है. पहले रीबूट के बाद से, उपयोगकर्ता डेटा में किए गए सभी बदलावों को हटा देता है.

फ़्रेमवर्क, रीबूट के बाद, लेकिन commitChanges से पहले इस तरीके को कॉल करता है. इस तरीके को कॉल करने पर, retry_counter कम हो जाता है. लॉग एंट्री जनरेट की जाती हैं.

bool needsRollback()

यह तय करता है कि रोलबैक की ज़रूरत है या नहीं.

बिना चेकपॉइंट वाले डिवाइसों पर, false दिखाता है. चेकपॉइंट डिवाइसों पर, नॉन-चेकपॉइंट बूट के दौरान true दिखाता है.

यूडीसी लागू करना

रेफ़रंस के तौर पर लागू करना

यूडीसी को लागू करने के तरीके का उदाहरण देखने के लिए, dm-bow.c देखें. इस सुविधा के बारे में ज़्यादा दस्तावेज़ देखने के लिए, dm-bow.txt देखें.

सेटअप

अपनी init.hardware.rc फ़ाइल में on fs में, पक्का करें कि आपके पास ये चीज़ें हों:

mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --early

अपनी init.hardware.rc फ़ाइल में on late-fs में, पक्का करें कि आपके पास ये चीज़ें हों:

mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late

पक्का करें कि आपकी fstab.hardware फ़ाइल में, /data को latemount के तौर पर टैग किया गया हो.

/dev/block/bootdevice/by-name/userdata              /data              f2fs
noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier
latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M,checkpoint=fs

मेटाडेटा का पार्टीशन जोड़ना

UDC को मेटाडेटा पार्टिशन की ज़रूरत होती है, ताकि नॉन-बूटलोडर की कोशिश की संख्या और कुंजियों को स्टोर किया जा सके. मेटाडेटा पार्टिशन सेट अप करें और उसे /metadata पर पहले से माउंट करें.

पक्का करें कि आपकी fstab.hardware फ़ाइल में, /metadata को earlymount या first_stage_mount के तौर पर टैग किया गया हो.

/dev/block/by-name/metadata           /metadata           ext4
noatime,nosuid,nodev,discard,sync
wait,formattable,first_stage_mount

पार्टीशन को सभी शून्य पर शुरू करें.

BoardConfig.mk में ये लाइनें जोड़ें:

BOARD_USES_METADATA_PARTITION := true
BOARD_ROOT_EXTRA_FOLDERS := existing_folders metadata

सिस्टम अपडेट करना

F2FS सिस्टम

डेटा को फ़ॉर्मैट करने के लिए F2FS का इस्तेमाल करने वाले सिस्टम के लिए, पक्का करें कि आपके पास F2FS का ऐसा वर्शन हो जो चेकपॉइंट के साथ काम करता हो. ज़्यादा जानकारी के लिए, अलग-अलग फ़ाइल सिस्टम में चेकपॉइंट की सुविधा लेख पढ़ें.

/data पर माउंट किए गए डिवाइस के लिए, fstab के <fs_mgr_flags> सेक्शन में checkpoint=fs फ़्लैग जोड़ें.

ऐसे सिस्टम जो F2FS नहीं हैं

F2FS सिस्टम के अलावा, अन्य सिस्टम के लिए कर्नेल कॉन्फ़िगरेशन में dm-bow चालू होना चाहिए.

/data पर माउंट किए गए डिवाइस के लिए, fstab के <fs_mgr_flags> सेक्शन में checkpoint=block फ़्लैग जोड़ें.

लॉग देखना

Checkpoint API को कॉल करने पर, लॉग एंट्री जनरेट होती हैं.

पुष्टि करें

यूडीसी लागू करने की जांच करने के लिए, VtsKernelCheckpointTest वीटीएस जांच का सेट चलाएं.