Görüntüleme desteği

Görüntüleme ağına özel bu alanlarda yapılan güncellemeler aşağıda verilmiştir:

Etkinlikleri ve ekranları yeniden boyutlandırma

Bir uygulamanın çok pencereli modu veya yeniden boyutlandırmayı desteklemeyebileceğini belirtmek için etkinliklerde resizeableActivity=false özelliği kullanılır. Etkinlikler yeniden boyutlandırıldığında uygulamaların karşılaştığı yaygın sorunlar şunlardır:

  • Bir etkinlik, uygulamadan veya başka bir görsel olmayan bileşenden farklı bir yapılandırmaya sahip olabilir. Sık yapılan bir hata, görüntüleme metriklerini uygulama bağlamından okumaktır. Döndürülen değerler, bir etkinliğin görüntülendiği görünür alan metriklerine göre ayarlanmaz.
  • Bir etkinlik, yeniden boyutlandırmayı işlemeyip kilitlenebilir, kullanıcı arayüzünü bozuk gösterebilir veya örnek durumu kaydedilmeden yeniden başlatıldığı için durumu kaybedebilir.
  • Bir uygulama, mutlak giriş koordinatlarını (pencere konumuna göre olanlar yerine) kullanmaya çalışabilir. Bu durum, çok pencereli modda girişi bozabilir.

Android 7 (ve sonraki sürümlerde) bir uygulama resizeableActivity=false her zaman tam ekran modunda çalışacak şekilde ayarlanabilir. Bu durumda platform, yeniden boyutlandırılamayan etkinliklerin bölünmüş ekrana geçmesini engeller. Kullanıcı, başlatıcıdan yeniden boyutlandırılamayan bir etkinliği halihazırda bölünmüş ekran modundayken çağırmaya çalışırsa platform, bölünmüş ekran modundan çıkar ve yeniden boyutlandırılamayan etkinliği tam ekran modunda başlatır.

Manifestte bu özelliği açıkça false olarak ayarlayan uygulamalar, uyumluluk modu uygulanmadığı sürece çoklu pencere modunda başlatılmamalıdır:

  • Tüm etkinlikleri ve etkinlik dışı bileşenleri içeren işleme aynı yapılandırma uygulanır.
  • Uygulanan yapılandırma, uygulamayla uyumlu ekranlar için CDD koşullarını karşılıyor.

Android 10'da platform, yeniden boyutlandırılamayan etkinliklerin bölünmüş ekran moduna geçmesini engellemeye devam eder ancak etkinlik sabit bir yön veya en boy oranı beyan ettiyse bu etkinlikler geçici olarak ölçeklendirilebilir. Aksi takdirde, etkinlik Android 9 ve önceki sürümlerde olduğu gibi ekranın tamamını kaplayacak şekilde yeniden boyutlandırılır.

Varsayılan uygulama aşağıdaki politikayı uygular:

android:resizeableActivity özelliği kullanılarak çoklu pencereyle uyumsuz olduğu belirtilen bir etkinlik, aşağıda açıklanan koşullardan birini karşıladığında ve uygulanan ekran yapılandırmasının değiştirilmesi gerektiğinde etkinlik ve işlem, orijinal yapılandırmayla kaydedilir. Kullanıcıya, güncellenen ekran yapılandırmasını kullanmak için uygulama işlemini yeniden başlatma olanağı sunulur.

  • android:screenOrientation uygulanarak sabit yönlendirme yapılıyor mu?
  • Uygulama, API düzeyini hedefleyerek varsayılan maksimum veya minimum en-boy oranına sahip ya da en-boy oranını açıkça belirtiyor

Bu şekilde, en boy oranı belirtilmiş ve yeniden boyutlandırılamayan bir etkinlik gösterilmektedir. Cihaz katlandığında pencere, uygun letterboxing kullanılarak en boy oranı korunurken alana sığacak şekilde küçültülür. Ayrıca, etkinliğin gösterim alanı her değiştirildiğinde kullanıcıya etkinliği yeniden başlatma seçeneği sunulur.

Cihaz açıldığında etkinliğin yapılandırması, boyutu ve en-boy oranı değişmez ancak etkinliği yeniden başlatma seçeneği gösterilir.

resizeableActivity ayarlanmadığında (veya true olarak ayarlandığında) uygulama, yeniden boyutlandırmayı tam olarak destekler.

Uygulama

Sabit yönlendirme veya en-boy oranına sahip, yeniden boyutlandırılamayan etkinliklere kodda boyut uyumluluğu modu (SCM) adı verilir. Koşul, ActivityRecord#shouldUseSizeCompatMode() adresinde tanımlanmıştır. Bir SCM etkinliği başlatıldığında, ekranla ilgili yapılandırma (ör. boyut veya yoğunluk) istenen geçersiz kılma yapılandırmasında sabitlenir. Böylece etkinlik artık mevcut ekran yapılandırmasına bağlı olmaz.

SCM etkinliği ekranın tamamını dolduramıyorsa üstte hizalanır ve yatay olarak ortalanır. Etkinlik sınırları AppWindowToken#calculateCompatBoundsTransformation() tarafından hesaplanır.

Bir SCM etkinliği, kapsayıcısından farklı bir ekran yapılandırması kullandığında (ör. ekran yeniden boyutlandırıldığında veya etkinlik başka bir ekrana taşındığında) ActivityRecord#inSizeCompatMode() doğru olur ve SizeCompatModeActivityController (Sistem kullanıcı arayüzünde) işlem yeniden başlatma düğmesini göstermek için geri çağırma alır.

Görüntü boyutları ve en boy oranları

Android 10, uzun ve ince ekranların yüksek oranlarından 1:1 oranlarına kadar yeni en boy oranları için destek sunar. Uygulamalar, ekranın ApplicationInfo#maxAspectRatio ve ApplicationInfo#minAspectRatio kısımlarını tanımlayabilir.

Android 10'daki uygulama oranları

1. şekil. Android 10'da desteklenen örnek uygulama oranları

Cihaz uygulamalarında, Android 9 ve sonraki sürümlerin gerektirdiği boyut ve çözünürlüklerden daha küçük boyut ve çözünürlüklere sahip ikincil ekranlar (minimum 2, 5 inç genişlik veya yükseklik, smallestScreenWidth için minimum 320 DP) bulunabilir ancak yalnızca bu küçük ekranları desteklemeyi tercih eden etkinlikler buraya yerleştirilebilir.

Uygulamalar, hedef ekran boyutundan küçük veya ona eşit bir minimum desteklenen boyut bildirerek bu özelliği etkinleştirebilir. Bunu yapmak için AndroidManifest'te android:minHeight ve android:minWidth etkinlik düzeni özelliklerini kullanın.

Görüntüleme politikaları

Android 10, belirli ekran politikalarını varsayılan WindowManagerPolicy uygulamasından ayırıp PhoneWindowManager ekran başına sınıflara taşır. Örneğin:

  • Görüntüleme durumu ve döndürme
  • Bazı tuşlar ve hareket etkinliği izleme
  • Sistem kullanıcı arayüzü ve dekorasyon pencereleri

Android 9 ve önceki sürümlerde PhoneWindowManager sınıfı; ekran politikalarını, durumu ve ayarları, döndürmeyi, dekorasyon pencere çerçevesi izlemeyi ve daha fazlasını yönetiyordu. Android 10, rotasyon izleme dışında bu işlevlerin çoğunu DisplayPolicy sınıfına taşır. Rotasyon izleme ise DisplayRotation sınıfına taşınmıştır.

Görüntü penceresi ayarları

Android 10'da, yapılandırılabilir ekran başına pencere ayarı aşağıdakileri içerecek şekilde genişletildi:

  • Varsayılan görüntüleme pencere modu
  • Aşırı tarama değerleri
  • Kullanıcı döndürme ve döndürme modu
  • Zorunlu boyut, yoğunluk ve ölçekleme modu
  • İçerik kaldırma modu (ekran kaldırıldığında)
  • Sistem süslemeleri ve IME için destek

DisplayWindowSettings sınıfı, bu seçeneklerin ayarlarını içerir. Ayarlar her değiştirildiğinde /data bölümündeki diske kaydedilir.display_settings.xml Ayrıntılı bilgi için DisplayWindowSettings.AtomicFileStorage ve DisplayWindowSettings#writeSettings() sayfalarını inceleyin. Cihaz üreticileri, cihaz yapılandırmaları için display_settings.xml varsayılan değerler sağlayabilir. Ancak dosya /data içinde depolandığı için silme işlemiyle silinen dosyaların geri yüklenmesi için ek mantık gerekebilir.

Android 10, ayarları kalıcı hale getirirken varsayılan olarak ekran için tanımlayıcı olarak DisplayInfo#uniqueId kullanır. uniqueId, tüm gösterimler için doldurulmalıdır. Ayrıca, fiziksel ve ağ ekranlarında da kararlıdır. Tanımlayıcı olarak fiziksel bir ekranın bağlantı noktasını da kullanabilirsiniz. Bu bağlantı noktası DisplayWindowSettings#mIdentifier bölümünde ayarlanabilir. Her yazma işleminde tüm ayarlar yazılır. Bu nedenle, depolamada bir görüntüleme girişi için kullanılan anahtarın güncellenmesi güvenlidir. Ayrıntılar için Statik reklam kimlikleri başlıklı makaleyi inceleyin.

Ayarlar, geçmiş nedenlerden dolayı /data dizininde kalıcı olarak saklanır. Başlangıçta, ekran döndürme gibi kullanıcı tarafından ayarlanan ayarları kalıcı hale getirmek için kullanılıyordu.

Statik ekran tanımlayıcıları

Android 9 (ve önceki sürümler), çerçevedeki ekranlar için kararlı tanımlayıcılar sağlamıyordu. Sisteme bir ekran eklendiğinde, statik bir sayaç artırılarak bu ekran için Display#mDisplayId veya DisplayInfo#displayId oluşturulur. Sistem aynı ekranı ekleyip kaldırdığında farklı bir kimlik oluşuyordu.

Bir cihazda önyükleme sırasında birden fazla ekran varsa zamanlamaya bağlı olarak ekranlara farklı tanımlayıcılar atanabilir. Android 9 (ve önceki sürümler) DisplayInfo#uniqueId içerse de fiziksel ekranlar yerleşik ve harici ekranı temsil etmek için local:0 veya local:1 olarak tanımlandığından ekranlar arasında ayrım yapmaya yetecek kadar bilgi içermiyordu.

Android 10'da DisplayInfo#uniqueId kararlı bir tanımlayıcı eklemek ve yerel, ağ ve sanal ekranlar arasında ayrım yapmak için değişiklikler yapıldı.

Görüntüleme türü Biçim
Yerel
local:<stable-id>
network:<mac-address>
Sanal
virtual:<package-name-and-name>

uniqueId güncellemelerine ek olarak DisplayInfo.address, yeniden başlatma işlemleri arasında sabit kalan bir ekran tanımlayıcısı olan DisplayAddress içerir. Android 10'da DisplayAddress, fiziksel ve ağ ekranlarını destekler. DisplayAddress.Physical, sabit bir görüntüleme kimliği içerir (uniqueId ile aynı) ve DisplayAddress#fromPhysicalDisplayId() ile oluşturulabilir.

Android 10, bağlantı noktası bilgilerini (Physical#getPort()) almak için de uygun bir yöntem sunar. Bu yöntem, ekranları statik olarak tanımlamak için çerçevede kullanılabilir. Örneğin, DisplayWindowSettings içinde kullanılır. DisplayAddress.Network, MAC adresini içerir ve DisplayAddress#fromMacAddress() ile oluşturulabilir.

Bu eklemeler, cihaz üreticilerinin statik çoklu ekran kurulumlarındaki ekranları tanımlamasına ve fiziksel ekran bağlantı noktaları gibi statik ekran tanımlayıcılarını kullanarak farklı sistem ayarlarını ve özelliklerini yapılandırmasına olanak tanır. Bu yöntemler gizlidir ve yalnızca system_server içinde kullanılmak üzere tasarlanmıştır.

Bu yöntem, HWC ekran kimliği (opak olabilir ve her zaman kararlı olmayabilir) verildiğinde ekran çıkışı için fiziksel bir bağlayıcıyı tanımlayan (platforma özgü) 8 bitlik bağlantı noktası numarasını ve ekranın EDID blob'unu döndürür. SurfaceFlinger, çerçeveye sunulan kararlı 64 bit ekran kimliklerini oluşturmak için EDID'den üretici veya model bilgilerini ayıklar. Bu yöntem desteklenmiyorsa veya hata veriyorsa SurfaceFlinger, yukarıda açıklandığı gibi DisplayInfo#address değerinin boş ve DisplayInfo#uniqueId değerinin sabit kodlu olduğu eski MD moduna geri döner.

Bu özelliğin desteklendiğini doğrulamak için şunu çalıştırın:

$ dumpsys SurfaceFlinger --display-id
# Example output.
Display 21691504607621632 (HWC display 0): port=0 pnpId=SHP displayName="LQ123P1JX32"
Display 9834494747159041 (HWC display 2): port=1 pnpId=HWP displayName="HP Z24i"
Display 1886279400700944 (HWC display 1): port=2 pnpId=AUS displayName="ASUS MB16AP"

İkiden fazla ekran kullanma

Android 9 ve önceki sürümlerde SurfaceFlinger ve DisplayManagerService 0 ve 1 kimlikleri sabit kodlanmış en fazla iki fiziksel ekranın varlığını varsayıyordu.

Android 10'dan itibaren SurfaceFlinger, kararlı ekran kimlikleri oluşturmak için bir Hardware Composer (HWC) API'sinden yararlanabilir. Bu sayede, rastgele sayıda fiziksel ekranı yönetebilir. Daha fazla bilgi için Statik ekran tanımlayıcıları başlıklı makaleyi inceleyin.

Çerçeve, SurfaceControl#getPhysicalDisplayIds veya DisplayEventReceiver hotplug etkinliğinden 64 bitlik ekran kimliğini aldıktan sonra SurfaceControl#getPhysicalDisplayToken aracılığıyla fiziksel bir ekran için IBinder jetonunu arayabilir.

Android 10 ve önceki sürümlerde birincil dahili ekran TYPE_INTERNAL, tüm ikincil ekranlar ise bağlantı türünden bağımsız olarak TYPE_EXTERNAL şeklinde işaretlenir. Bu nedenle, ek dahili ekranlar harici olarak değerlendirilir. Geçici çözüm olarak, cihaza özel kod, HWC'nin bilinip bilinmediği ve bağlantı noktası tahsisi mantığının tahmin edilebilir olup olmadığı hakkında varsayımlarda bulunabilir.DisplayAddress.Physical#getPort

Bu sınırlama Android 11 ve sonraki sürümlerde kaldırılmıştır.

  • Android 11'de başlatma sırasında bildirilen ilk ekran, birincil ekrandır. Bağlantı türü (dahili veya harici) önemli değildir. Ancak birincil ekranın bağlantısının kesilemeyeceği ve bu nedenle uygulamada dahili bir ekran olması gerektiği doğrudur. Bazı katlanabilir telefonlarda birden fazla iç ekran olduğunu unutmayın.
  • İkincil ekranlar, bağlantı türlerine bağlı olarak doğru şekilde Display.TYPE_INTERNAL veya Display.TYPE_EXTERNAL (önceki adlarıyla Display.TYPE_BUILT_IN ve Display.TYPE_HDMI) olarak sınıflandırılır.

Uygulama

Android 9 ve önceki sürümlerde ekranlar 32 bitlik kimliklerle tanımlanır. Burada 0 dahili ekranı, 1 harici ekranı, [2, INT32_MAX] HWC sanal ekranlarını ve -1 geçersiz bir ekranı veya HWC olmayan bir sanal ekranı temsil eder.

Android 10'dan itibaren ekranlara sabit ve kalıcı kimlikler verilir. Bu sayede SurfaceFlinger ve DisplayManagerService, ikiden fazla ekranı izleyebilir ve daha önce görülen ekranları tanıyabilir. HWC, IComposerClient.getDisplayIdentificationData'yi destekliyorsa ve ekran tanımlama verileri sağlıyorsa SurfaceFlinger, EDID yapısını ayrıştırır ve fiziksel ile HWC sanal ekranları için sabit 64 bit ekran kimlikleri ayırır. Kimlikler, bir seçenek türü kullanılarak ifade edilir. Burada boş değer, geçersiz bir ekranı veya HWC olmayan sanal ekranı temsil eder. HWC desteği olmadan SurfaceFlinger, en fazla iki fiziksel ekranla eski davranışa geri döner.

Ekran başına odaklanma

Android 10, aynı anda tek tek ekranları hedefleyen çeşitli giriş kaynaklarını desteklemek için birden fazla odaklanmış pencereyi (ekran başına en fazla bir tane) destekleyecek şekilde yapılandırılabilir. Bu özellik yalnızca birden fazla kullanıcının aynı anda aynı cihazla etkileşimde bulunduğu ve farklı giriş yöntemleri veya cihazlar (ör. Android Automotive) kullandığı özel cihaz türleri için tasarlanmıştır.

Bu özelliğin, çok ekranlı cihazlar veya masaüstü benzeri deneyimler için kullanılanlar da dahil olmak üzere normal cihazlarda etkinleştirilmemesi önemle tavsiye edilir. Bunun temel nedeni, kullanıcıların hangi pencerenin giriş odağına sahip olduğunu merak etmesine neden olabilecek bir güvenlik sorunudur.

Kullanıcının bir metin giriş alanına güvenli bilgiler girdiğini düşünün. Örneğin, bankacılık uygulamasına giriş yapıyor veya hassas bilgiler içeren metin giriyor. Kötü amaçlı bir uygulama, bir etkinliği yürütmek için ekran dışı sanal bir ekran oluşturabilir. Bu ekranda bir metin giriş alanı da bulunur. Hem meşru hem de kötü amaçlı etkinlikler odaklanma durumundadır ve her ikisinde de etkin bir giriş göstergesi (yanıp sönen imleç) bulunur.

Ancak klavyeden (donanım veya yazılım) gelen giriş yalnızca en üstteki etkinliğe (en son başlatılan uygulama) girildiğinden, kötü amaçlı bir uygulama gizli bir sanal ekran oluşturarak kullanıcı girişini, birincil cihaz ekranında yazılım klavyesi kullanırken bile alabilir.

Ekran başına odak ayarlamak için com.android.internal.R.bool.config_perDisplayFocusEnabled simgesini kullanın.

Uyumluluk

Sorun: Android 9 ve önceki sürümlerde sistemdeki pencerelerden en fazla biri aynı anda odaklanabilir.

Çözüm: Aynı işleme ait iki pencerenin odaklandığı nadir durumlarda sistem, yalnızca Z düzeninde daha yüksek olan pencereye odaklanır. Bu kısıtlama, Android 10'u hedefleyen uygulamalar için kaldırılır. Bu noktada, uygulamaların aynı anda odaklanılan birden fazla pencereyi desteklemesi beklenir.

Uygulama

WindowManagerService#mPerDisplayFocusEnabled, bu özelliğin kullanılabilirliğini kontrol eder. ActivityManager içinde, değişkenlerde artık genel izleme yerine ActivityDisplay#getFocusedStack() kullanılıyor. ActivityDisplay#getFocusedStack() Değeri önbelleğe almak yerine Z sırasına göre odaklanmayı belirler. Bunun nedeni, etkinliklerin Z sırasını yalnızca bir kaynağın (WindowManager) izlemesi gerektiğidir.

ActivityStackSupervisor#getTopDisplayFocusedStack(), sistemdeki en üstteki odaklanılmış yığın tanımlanması gerektiğinde benzer bir yaklaşım kullanır. Yığınlar yukarıdan aşağıya doğru geçilerek ilk uygun yığın aranır.

InputDispatcher artık birden fazla odaklanmış pencereye sahip olabilir (ekran başına bir tane). Bir giriş etkinliği ekrana özelse ilgili ekrandaki odaklanılmış pencereye gönderilir. Aksi takdirde, kullanıcı tarafından en son etkileşimde bulunulan ekran olan odaklanılan ekrandaki odaklanılan pencereye gönderilir.

InputDispatcher::mFocusedWindowHandlesByDisplay ve InputDispatcher::setFocusedDisplay() hükümlerini inceleyin. Odaklanmış uygulamalar da InputManagerService'te NativeInputManager::setFocusedApplication() aracılığıyla ayrı ayrı güncellenir.

WindowManager'da odaklanılan pencereler de ayrı olarak izlenir. DisplayContent#mCurrentFocus ve DisplayContent#mFocusedApp ile ilgili kullanım alanlarını inceleyin. İlgili odak izleme ve güncelleme yöntemleri WindowManagerService konumundan DisplayContent konumuna taşındı.