Görüntüleme ağına özel bu alanlarda yapılan güncellemeler aşağıda verilmiştir:
- Etkinlikleri ve ekranları yeniden boyutlandırma
- Görüntü boyutları ve en boy oranları
- Görüntüleme politikaları
- Görüntüleme penceresi ayarları
- Statik ekran tanımlayıcıları
- İkiden fazla ekran kullanma
- Görüntüleme başına odaklanma
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.
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> |
Ağ | 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
veyaDisplay.TYPE_EXTERNAL
(önceki adlarıylaDisplay.TYPE_BUILT_IN
veDisplay.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ı.