A/B (kesintisiz) sistem güncellemeleri

Kesintisiz güncellemeler olarak da bilinen A/B sistem güncellemeleri, kablosuz (OTA) güncelleme sırasında diskte çalışır durumda bir önyükleme sisteminin kalmasını sağlar. Bu yaklaşım, güncelleme sonrasında cihazın etkin olmaması olasılığını azaltır; bu da onarım ve garanti merkezlerinde daha az cihaz değişimi ve cihazın yeniden başlatılması anlamına gelir. ChromeOS gibi diğer ticari sınıf işletim sistemleri de A/B güncellemelerini başarıyla kullanır.

A/B sistemi güncellemeleri ve bunların nasıl çalıştığı hakkında daha fazla bilgi için bkz . Bölüm seçimi (yuvalar) .

A/B sistem güncellemeleri aşağıdaki avantajları sağlar:

  • OTA güncellemeleri sistem çalışırken kullanıcıyı kesintiye uğratmadan gerçekleşebilir. Kullanıcılar OTA sırasında cihazlarını kullanmaya devam edebilir; güncelleme sırasındaki tek kesinti, cihazın güncellenen disk bölümüne yeniden başlatılmasıdır.
  • Güncellemeden sonra yeniden başlatma, normal yeniden başlatmadan daha uzun sürmez.
  • Bir OTA uygulanamazsa (örneğin, hatalı flaş nedeniyle), kullanıcı etkilenmeyecektir. Kullanıcı eski işletim sistemini çalıştırmaya devam edecek ve istemci güncellemeyi yeniden denemekte özgürdür.
  • Bir OTA güncellemesi uygulanırsa ancak önyükleme başarısız olursa, cihaz eski bölüme yeniden başlatılır ve kullanılabilir durumda kalır. İstemci güncellemeyi yeniden denemekte özgürdür.
  • Herhangi bir hata (G/Ç hataları gibi) yalnızca kullanılmayan bölüm kümesini etkiler ve yeniden denenebilir. Kullanıcı deneyiminin bozulmasını önlemek için G/Ç yükünün kasıtlı olarak düşük tutulması nedeniyle bu tür hataların olasılığı da azalıyor.
  • Güncellemeler A/B cihazlarına aktarılabilir, böylece paketi kurmadan önce indirme ihtiyacı ortadan kalkar. Akış, kullanıcının güncelleme paketini /data veya /cache üzerinde depolamak için yeterli boş alana sahip olmasının gerekli olmadığı anlamına gelir.
  • Önbellek bölümü artık OTA güncelleme paketlerini depolamak için kullanılmadığından, önbellek bölümünün gelecekteki güncellemeler için yeterince büyük olduğundan emin olmanıza gerek yoktur.
  • dm-verity, bir cihazın bozulmamış bir görüntüyü önyükleyeceğini garanti eder. Bir cihaz, kötü bir OTA veya dm-verity sorunu nedeniyle önyükleme yapmazsa cihaz eski bir görüntüyle yeniden başlatılabilir. (Android Verified Boot, A/B güncellemeleri gerektirmez.)

A/B sistemi güncellemeleri hakkında

A/B güncellemeleri hem istemcide hem de sistemde değişiklik yapılmasını gerektirir. Ancak OTA paket sunucusu değişiklik gerektirmemelidir: güncelleme paketleri hâlâ HTTPS üzerinden sunulmaktadır. Google'ın OTA altyapısını kullanan cihazlarda sistem değişikliklerinin tamamı AOSP'de olup, client kodu Google Play servisleri tarafından sağlanmaktadır. Google'ın OTA altyapısını kullanmayan OEM'ler AOSP sistem kodunu yeniden kullanabilecek ancak kendi istemcilerini sağlamaları gerekecek.

Kendi müşterilerine tedarik sağlayan OEM'ler için müşterinin şunları yapması gerekir:

  • Ne zaman güncelleme alacağınıza karar verin. A/B güncellemeleri arka planda gerçekleştiğinden artık kullanıcı tarafından başlatılmaz. Kullanıcıların rahatsız edilmesini önlemek için güncellemelerin, cihaz gece boyunca boşta bakım modundayken ve Wi-Fi'deyken planlanması önerilir. Ancak müşteriniz istediğiniz buluşsal yöntemi kullanabilir.
  • OTA paket sunucularınıza danışın ve bir güncellemenin mevcut olup olmadığını belirleyin. Bu, cihazın A/B'yi desteklediğini belirtmek istemeniz dışında çoğunlukla mevcut müşteri kodunuzla aynı olmalıdır. (Google'ın istemcisi ayrıca kullanıcıların en son güncellemeyi kontrol edebilmesi için bir Şimdi kontrol et düğmesi içerir.)
  • Güncelleme paketinizin mevcut olduğunu varsayarak, güncelleme paketinizin HTTPS URL'si ile update_engine çağırın. update_engine güncelleme paketini aktarırken şu anda kullanılmayan bölümdeki ham blokları güncelleyecektir.
  • update_engine sonuç koduna göre kurulum başarılarını veya başarısızlıklarını sunucularınıza bildirin. Güncelleme başarıyla uygulanırsa update_engine , önyükleyiciye bir sonraki yeniden başlatmada yeni işletim sistemine önyükleme yapmasını söyleyecektir. Yeni işletim sistemi önyükleme yapamazsa, önyükleyici eski işletim sistemine geri dönecektir, dolayısıyla istemcinin herhangi bir işlem yapmasına gerek yoktur. Güncelleme başarısız olursa, istemcinin ayrıntılı hata koduna göre ne zaman tekrar deneyeceğine (ve deneyip denemeyeceğine) karar vermesi gerekir. Örneğin, iyi bir müşteri kısmi ("diff") OTA paketinin başarısız olduğunu fark edebilir ve bunun yerine tam bir OTA paketini deneyebilir.

İsteğe bağlı olarak müşteri şunları yapabilir:

  • Kullanıcının yeniden başlatmasını isteyen bir bildirim gösterin. Kullanıcının rutin olarak güncelleme yapmasının teşvik edildiği bir politika uygulamak istiyorsanız bu bildirim istemcinize eklenebilir. İstemci kullanıcılara istemde bulunmazsa kullanıcılar bir sonraki yeniden başlatmalarında güncellemeyi yine de alırlar. (Google'ın istemcisinde güncelleme başına yapılandırılabilir bir gecikme vardır.)
  • Kullanıcılara yeni bir işletim sistemi sürümüne mi önyükleme yaptıklarını veya bunu yapmaları beklenip eski işletim sistemi sürümüne mi geri döndüklerini bildiren bir bildirim gösterin. (Google'ın istemcisi genellikle ikisini de yapmaz.)

Sistem tarafında, A/B sistem güncellemeleri aşağıdakileri etkiler:

  • Bölüm seçimi (yuvalar), update_engine arka plan programı ve önyükleyici etkileşimleri (aşağıda açıklanmıştır)
  • Derleme süreci ve OTA güncelleme paketi oluşturma ( A/B Güncellemelerini Uygulama bölümünde açıklanmıştır)

Bölüm seçimi (yuvalar)

A/B sistem güncellemeleri, yuvalar olarak adlandırılan iki bölüm kümesini kullanır (normalde yuva A ve yuva B). Sistem mevcut yuvadan çalışır, ancak normal çalışma sırasında kullanılmayan yuvadaki bölümlere çalışan sistem tarafından erişilmez. Bu yaklaşım, kullanılmayan yuvayı bir geri dönüş olarak tutarak güncellemeleri hatalara karşı dayanıklı hale getirir: Güncelleme sırasında veya hemen sonrasında bir hata meydana gelirse, sistem eski yuvaya geri dönebilir ve çalışan bir sisteme sahip olmaya devam edebilir. Bu amaca ulaşmak için, mevcut yuva tarafından kullanılan hiçbir bölüm, OTA güncellemesinin bir parçası olarak güncellenmemelidir (yalnızca bir kopyanın bulunduğu bölümler dahil).

Her yuvanın, yuvanın aygıtın önyükleme yapabileceği doğru sistemi içerip içermediğini belirten önyüklenebilir bir özelliği vardır. Geçerli yuva, sistem çalışırken önyüklenebilir, ancak diğer yuvada sistemin eski (hala doğru) bir sürümü, daha yeni bir sürümü veya geçersiz veriler bulunabilir. Geçerli yuvanın ne olduğuna bakılmaksızın, etkin yuva (önyükleyicinin bir sonraki önyüklemede önyükleme yapacağı yuva) veya tercih edilen yuva olan bir yuva vardır.

Her yuva aynı zamanda kullanıcı alanı tarafından belirlenen başarılı bir özniteliğe sahiptir ve bu yalnızca yuvanın önyüklenebilir olması durumunda geçerlidir. Başarılı bir slot kendini başlatabilmeli, çalıştırabilmeli ve güncelleyebilmelidir. Başarılı olarak işaretlenmeyen önyüklenebilir bir yuva (birkaç önyükleme denemesinden sonra), aktif yuvanın başka bir önyüklenebilir yuvayla (normalde önyükleme girişiminden hemen önce çalışan yuvaya) değiştirilmesi de dahil olmak üzere, önyükleyici tarafından önyüklenebilir olarak işaretlenmelidir. yeni, aktif olana). Arayüzün spesifik ayrıntıları boot_control.h dosyasında tanımlanmıştır.

Motor arka plan programını güncelle

A/B sistem güncellemeleri, sistemi yeni, güncellenmiş bir sürüme önyükleme yapmaya hazırlamak için update_engine adı verilen bir arka plan arka plan programı kullanır. Bu arka plan programı aşağıdaki eylemleri gerçekleştirebilir:

  • Geçerli yuva A/B bölümlerinden okuyun ve tüm verileri OTA paketinde belirtildiği şekilde kullanılmayan yuva A/B bölümlerine yazın.
  • Önceden tanımlanmış bir iş akışında boot_control arayüzünü çağırın.
  • OTA paketinde belirtildiği gibi, kullanılmayan tüm yuva bölümlerini yazdıktan sonra yeni bölümden bir kurulum sonrası programı çalıştırın. (Ayrıntılar için bkz . Kurulum sonrası ).

update_engine arka plan programı, önyükleme işleminin kendisine dahil olmadığından, mevcut yuvadaki SELinux politikaları ve özellikleri tarafından yapılan bir güncelleme sırasında yapabilecekleri sınırlıdır (bu tür politikalar ve özellikler, sistem bir önyükleme işlemine kadar güncellenemez). Yeni sürüm). Sistemin sağlamlığını korumak için güncelleme işlemi bölüm tablosunu, geçerli yuvadaki bölümlerin içeriğini veya fabrika ayarlarına sıfırlamayla silinemeyen A/B olmayan bölümlerin içeriğini değiştirmemelidir .

Motor kaynağını güncelle

update_engine kaynağı system/update_engine konumunda bulunur. A/B OTA dexopt dosyaları installd ve paket yöneticisi arasında bölünmüştür:

Çalışan bir örnek için /device/google/marlin/device-common.mk adresine bakın.

Motor günlüklerini güncelle

Android 8.x sürümleri ve önceki sürümleri için update_engine günlükleri logcat ve hata raporunda bulunabilir. update_engine günlüklerinin dosya sisteminde kullanılabilir olmasını sağlamak için aşağıdaki değişiklikleri yapınıza ekleyin:

Bu değişiklikler, en son update_engine günlüğünün bir kopyasını /data/misc/update_engine_log/update_engine. YEAR - TIME . Geçerli günlüğe ek olarak, en son beş günlük /data/misc/update_engine_log/ altına kaydedilir. Günlük grubu kimliğine sahip kullanıcılar, dosya sistemi günlüklerine erişebilecektir.

Önyükleyici etkileşimleri

boot_control HAL, update_engine (ve muhtemelen diğer servis programları) tarafından önyükleyiciye nereden önyükleneceği talimatını vermek için kullanılır. Yaygın örnek senaryolar ve bunlarla ilişkili durumlar aşağıdakileri içerir:

  • Normal durum : Sistem mevcut yuvasından (A veya B yuvası) çalışıyor. Şu ana kadar hiçbir güncelleme uygulanmadı. Sistemin mevcut yuvası önyüklenebilir, başarılı ve etkin yuvadır.
  • Güncelleme devam ediyor : Sistem B yuvasından çalışıyor, dolayısıyla B yuvası önyüklenebilir, başarılı ve etkin yuvadır. A yuvasının içeriği güncellendiğinden ancak henüz tamamlanmadığından, A yuvası önyüklenemez olarak işaretlendi. Bu durumdaki yeniden başlatma, B yuvasından önyüklemeye devam etmelidir.
  • Güncelleme uygulandı, yeniden başlatma bekleniyor : Sistem B yuvasından çalışıyor, B yuvası önyüklenebilir ve başarılı, ancak A yuvası etkin olarak işaretlendi (ve bu nedenle önyüklenebilir olarak işaretlendi). A Yuvası henüz başarılı olarak işaretlenmedi ve önyükleyici tarafından A yuvasından önyükleme yapmak için birkaç deneme yapılması gerekiyor.
  • Sistem yeni güncellemeyle yeniden başlatıldı : Sistem ilk kez A yuvasından çalışıyor, B yuvası hala önyüklenebilir ve başarılı, A yuvası ise yalnızca önyüklenebilir ve hala etkin ancak başarılı değil. Bir kullanıcı alanı arka plan programı update_verifier , bazı kontroller yapıldıktan sonra A yuvasını başarılı olarak işaretlemelidir.

Akış güncelleme desteği

Kullanıcı cihazları, güncelleme paketini indirmek için her zaman /data üzerinde yeterli alana sahip olmayabilir. Ne OEM'ler ne de kullanıcılar /cache bölümünde alan israf etmek istemediğinden, bazı kullanıcılar cihazın güncelleme paketini saklayacak yeri olmadığından güncelleme yapmadan kalır. Bu sorunu çözmek için Android 8.0, blokları /data üzerinde depolamaya gerek kalmadan indirilirken blokları doğrudan B bölümüne yazan A/B güncellemelerinin akışı için destek ekledi. Akışlı A/B güncellemeleri neredeyse hiç geçici depolamaya ihtiyaç duymaz ve yalnızca yaklaşık 100 KiB meta veri için yeterli depolama gerektirir.

Android 7.1'de akış güncellemelerini etkinleştirmek için aşağıdaki yamaları seçin:

Bu yamalar , Google Mobil Hizmetleri (GMS) veya başka bir güncelleme istemcisi kullanılarak Android 7.1 ve sonraki sürümlerde A/B güncelleme akışını desteklemek için gereklidir.

Bir A/B güncellemesinin ömrü

Güncelleme işlemi, bir OTA paketi (kodda yük olarak anılır) indirilmeye hazır olduğunda başlar. Cihazdaki politikalar, pil düzeyine, kullanıcı etkinliğine, şarj durumuna veya diğer politikalara bağlı olarak veri yükünün indirilmesini ve uygulamasını erteleyebilir. Ayrıca güncelleme arka planda çalıştığı için kullanıcılar güncellemenin devam ettiğini bilmeyebilir. Tüm bunlar, güncelleme işleminin politikalar, beklenmeyen yeniden başlatmalar veya kullanıcı eylemleri nedeniyle herhangi bir noktada kesintiye uğrayabileceği anlamına gelir.

İsteğe bağlı olarak OTA paketindeki meta veriler, güncellemenin yayınlanabileceğini gösterir; aynı paket akışsız kurulum için de kullanılabilir. Sunucu, istemciye akış yaptığını bildirmek için meta verileri kullanabilir, böylece istemci OTA'yı update_engine doğru şekilde aktarır. Kendi sunucuları ve istemcileri olan cihaz üreticileri, sunucunun güncellemenin akış halinde olduğunu tanımlamasını (veya tüm güncellemelerin akış halinde olduğunu varsaymasını) ve istemcinin akış için update_engine doğru çağrıyı yapmasını sağlayarak akış güncellemelerini etkinleştirebilir. Üreticiler, istemciye akış olarak çerçeve tarafına aktarımı tetiklemek üzere bir bayrak göndermek için paketin akış varyantında olduğu gerçeğini kullanabilir.

Bir veri kullanılabilir hale geldikten sonra güncelleme işlemi aşağıdaki gibidir:

Adım Faaliyetler
1 Geçerli yuva (veya "kaynak yuva"), markBootSuccessful() ile başarılı olarak işaretlenir (önceden işaretlenmemişse).
2 Kullanılmayan yuva (veya "hedef yuva") setSlotAsUnbootable() işlevi çağrılarak önyükleme yapılamaz olarak işaretlenir. Önyükleyicinin, yakında geçersiz verilere sahip olacak kullanılmayan yuvaya geri dönmesini önlemek için, mevcut yuva güncellemenin başlangıcında her zaman başarılı olarak işaretlenir. Sistem bir güncellemeyi uygulamaya başlayabilecek noktaya ulaştıysa, diğer ana bileşenler bozulsa bile (çökme döngüsündeki kullanıcı arayüzü gibi) mevcut yuva başarılı olarak işaretlenir, çünkü bunları düzeltmek için yeni bir yazılım göndermek mümkündür. sorunlar.

Güncelleme verisi, yeni sürüme güncelleme talimatlarını içeren opak bir blobdur. Güncelleme yükü aşağıdakilerden oluşur:
  • Meta veriler . Güncelleme yükünün nispeten küçük bir kısmı olan meta veriler, hedef yuvada yeni sürümün üretilmesi ve doğrulanması için yapılan işlemlerin bir listesini içerir. Örneğin, bir işlem belirli bir blobun sıkıştırmasını açabilir ve onu hedef bölümdeki belirli bloklara yazabilir veya kaynak bölümden okuyabilir, ikili yama uygulayabilir ve hedef bölümdeki belirli bloklara yazabilir.
  • Ekstra veriler . Güncelleme yükünün büyük bir kısmını oluşturan işlemlerle ilişkili ekstra veriler, bu örneklerde sıkıştırılmış blob veya ikili yamadan oluşur.
3 Yük meta verileri indirilir.
4 Metadata'da tanımlanan her işlem için sırasıyla ilgili veriler (varsa) belleğe indirilir, işlem uygulanır ve ilgili bellek atılır.
5 Tüm bölümler yeniden okunur ve beklenen karma değerine göre doğrulanır.
6 Kurulum sonrası adım (varsa) çalıştırılır. Herhangi bir adımın yürütülmesi sırasında bir hata olması durumunda güncelleme başarısız olur ve muhtemelen farklı bir veri yüküyle yeniden denenir. Şu ana kadarki tüm adımlar başarılı olduysa güncelleme başarılı olur ve son adım yürütülür.
7 Kullanılmayan yuva, setActiveBootSlot() çağrılarak etkin olarak işaretlenir. Kullanılmayan yuvanın etkin olarak işaretlenmesi, önyüklemenin tamamlanacağı anlamına gelmez. Önyükleyici (veya sistemin kendisi), başarılı bir durumu okumazsa aktif yuvayı geri değiştirebilir.
8 Kurulum sonrası (aşağıda açıklanmıştır), bir programın eski sürümde çalışırken "yeni güncelleme" sürümünden çalıştırılmasını içerir. OTA paketinde tanımlanmışsa bu adım zorunludur ve programın 0 çıkış koduyla dönmesi gerekir; aksi takdirde güncelleme başarısız olur.
9 Sistem yeni yuvaya yeterince başarılı bir şekilde önyükleme yaptıktan ve yeniden başlatma sonrası kontrolleri tamamladıktan sonra, şu anda geçerli olan yuva (eskiden "hedef yuva") markBootSuccessful() çağrılarak başarılı olarak işaretlenir.

Yükleme sonrası

Kurulum sonrası adımın tanımlandığı her bölüm için update_engine yeni bölümü belirli bir konuma bağlar ve bağlanan bölüme göre OTA'da belirtilen programı çalıştırır. Örneğin, kurulum sonrası program sistem bölümünde usr/bin/postinstall olarak tanımlanmışsa, kullanılmayan yuvadaki bu bölüm sabit bir konuma ( /postinstall_mount gibi) ve /postinstall_mount/usr/bin/postinstall dizinine monte edilecektir. /postinstall_mount/usr/bin/postinstall komutu yürütülür.

Kurulum sonrası başarılı olmak için eski çekirdeğin şunları yapabilmesi gerekir:

  • Yeni dosya sistemi formatını bağlayın . Sıkıştırılmış bir dosya sistemi (örn. SquashFS) kullanılıyorsa kullanılan sıkıştırma algoritması gibi ayrıntılar da dahil olmak üzere, eski çekirdekte destek olmadığı sürece dosya sistemi türü değişemez.
  • Yeni bölümün kurulum sonrası program formatını anlayın . Yürütülebilir ve Bağlanabilir Format (ELF) ikilisi kullanılıyorsa, eski çekirdekle uyumlu olmalıdır (örneğin, mimari 32-bit yapılardan 64-bit yapılara geçmişse, eski bir 32-bit çekirdek üzerinde çalışan 64-bit yeni bir program). Yükleyiciye ( ld ) başka yollar kullanması veya statik bir ikili oluşturması talimatı verilmediği sürece, kitaplıklar yenisinden değil eski sistem görüntüsünden yüklenecektir.

Örneğin, bir kabuk komut dosyasını, eski sistemin kabuk ikili dosyası tarafından #! ile yorumlanan bir kurulum sonrası program olarak kullanabilirsiniz. üstteki işaretçiyi kullanın), ardından daha karmaşık bir ikili kurulum sonrası programı yürütmek için yeni ortamdan kitaplık yollarını ayarlayın. Alternatif olarak, ana sistem bölümündeki dosya sistemi formatının geriye dönük uyumluluk sorunlarına veya atlama taşı güncellemelerine maruz kalmadan güncellenmesini sağlamak için kurulum sonrası adımını ayrılmış daha küçük bir bölümden çalıştırabilirsiniz; bu, kullanıcıların bir fabrika görüntüsünden doğrudan en son sürüme güncelleme yapmasına olanak tanır.

Yeni kurulum sonrası program, eski sistemde tanımlanan SELinux politikalarıyla sınırlıdır. Bu nedenle, kurulum sonrası adım, belirli bir cihazda tasarımın gerektirdiği görevlerin veya diğer en iyi çaba gerektiren görevlerin (örneğin, A/B özellikli ürün yazılımının veya önyükleyicinin güncellenmesi, veritabanlarının kopyalarının yeni sürüm için hazırlanması vb.) gerçekleştirilmesi için uygundur. ). Kurulum sonrası adım, yeniden başlatma öncesinde öngörülemeyen izinler gerektiren tek seferlik hata düzeltmeleri için uygun değildir .

Seçilen kurulum sonrası program, postinstall SELinux bağlamında çalışır. Yeni monte edilen bölümdeki tüm dosyalar, yeni sistemi yeniden başlattıktan sonra özniteliklerinin ne olduğuna bakılmaksızın postinstall_file ile etiketlenecektir. Yeni sistemdeki SELinux niteliklerinde yapılan değişiklikler kurulum sonrası adımı etkilemeyecektir. Kurulum sonrası programın ekstra izinlere ihtiyacı varsa, bunların kurulum sonrası içeriğe eklenmesi gerekir.

Yeniden başlatmanın ardından

Yeniden başlatmanın ardından update_verifier , dm-verity'yi kullanarak bütünlük kontrolünü tetikler. Bu kontrol, Java hizmetlerinin güvenli bir geri dönüşü engelleyecek geri dönüşü olmayan değişiklikler yapmasını önlemek için zigottan önce başlar. Bu işlem sırasında, doğrulanmış önyükleme veya dm-verity herhangi bir bozulma tespit ederse önyükleyici ve çekirdek de yeniden başlatmayı tetikleyebilir. Kontrol tamamlandıktan sonra update_verifier , önyüklemenin başarılı olduğunu işaretler.

update_verifier yalnızca AOSP kodunu kullanırken A/B OTA paketine dahil olan /data/ota_package/care_map.txt dosyasında listelenen blokları okuyacaktır. GmsCore gibi Java sistem güncelleme istemcisi care_map.txt dosyasını çıkarır, cihazı yeniden başlatmadan önce erişim iznini ayarlar ve sistem yeni sürüme başarıyla önyüklendikten sonra çıkarılan dosyayı siler.