Pembaruan yang dilakukan pada area khusus tampilan tersebut tercantum di bawah ini:
- Mengubah ukuran aktivitas dan layar
- Ukuran tampilan dan rasio aspek
- Kebijakan display
- Setelan jendela tampilan
- ID tampilan statis
- Menggunakan lebih dari dua layar
- Fokus per tampilan
Mengubah ukuran aktivitas dan layar
Untuk menunjukkan bahwa aplikasi mungkin tidak mendukung mode multi-aplikasi atau pengubahan ukuran,
aktivitas menggunakan atribut resizeableActivity=false
. Umum
masalah yang ditemukan oleh aplikasi saat aktivitas diubah ukurannya meliputi:
- Suatu aktivitas dapat memiliki konfigurasi yang berbeda dari aplikasi atau yang lainnya non-visual. Kesalahan umum adalah membaca metrik tampilan dari aplikasi konteks tambahan. Nilai yang ditampilkan tidak akan disesuaikan dengan metrik area yang terlihat tempat aktivitas ditampilkan.
- Suatu aktivitas mungkin tidak menangani pengubahan ukuran dan error, menampilkan UI yang terdistorsi, atau kehilangan status karena diluncurkan kembali tanpa menyimpan status instance.
- Aplikasi mungkin mencoba menggunakan koordinat input absolut (bukan koordinat input relatif terhadap posisi jendela), yang dapat merusak input di multi-aplikasi.
Di Android 7 (dan yang lebih tinggi), aplikasi dapat disetel
resizeableActivity=false
untuk selalu berjalan dalam mode layar penuh. Di beberapa
Dalam hal ini, platform mencegah aktivitas yang tidak dapat diubah ukurannya dibagi ke dalam pemisahan
layar. Jika pengguna mencoba memanggil aktivitas yang tidak dapat diubah ukurannya dari peluncur
saat berada dalam mode layar terpisah, platform
keluar dari mode layar terpisah dan
meluncurkan aktivitas yang tidak dapat diubah ukurannya dalam mode layar penuh.
Aplikasi yang secara eksplisit menetapkan atribut ini ke false
dalam
manifes tidak boleh diluncurkan dalam mode multi-aplikasi, kecuali jika
mode tersebut diterapkan:
- Konfigurasi yang sama diterapkan pada proses, yang berisi semua aktivitas dan non-aktivitas.
- Konfigurasi yang diterapkan memenuhi persyaratan CDD untuk aplikasi yang kompatibel layar.
Di Android 10, platform masih mencegah aktivitas yang tidak dapat diubah ukurannya agar tidak masuk ke mode layar terpisah, tetapi bisa juga diskalakan sementara jika aktivitas telah mendeklarasikan orientasi atau aspek tetap rasio. Jika tidak, aktivitas akan berubah ukuran untuk mengisi seluruh layar seperti di Android 9 dan lebih rendah.
Implementasi default menerapkan kebijakan berikut:
Ketika suatu aktivitas dideklarasikan tidak kompatibel dengan multi-aplikasi melalui
penggunaan atribut android:resizeableActivity
dan kapan
memenuhi salah satu kondisi yang dijelaskan di bawah ini, maka ketika diterapkan
konfigurasi layar harus diubah, aktivitas dan proses disimpan dengan
konfigurasi asli dan pengguna diberikan
kemampuan untuk meluncurkan kembali
proses aplikasi untuk menggunakan konfigurasi layar yang diupdate.
- Orientasi tetap melalui penerapan
android:screenOrientation
- Aplikasi memiliki rasio aspek maksimum atau minimum default dengan menargetkan level API atau mendeklarasikan rasio aspek secara eksplisit
Gambar ini menampilkan aktivitas yang tidak dapat diubah ukurannya dengan rasio aspek yang dideklarasikan. Saat perangkat dilipat, ukuran jendela akan diperkecil agar sesuai dengan area saat mempertahankan rasio aspek menggunakan tampilan lebar yang sesuai. Selain itu, opsi {i>restart activity<i} disediakan kepada pengguna setiap kali aktivitas diubah.
Saat membuka perangkat, konfigurasi, ukuran, dan rasio aspek aktivitas tidak berubah, namun opsi untuk memulai ulang aktivitas akan ditampilkan.
Jika resizeableActivity
tidak ditetapkan (atau ditetapkan ke
true
), aplikasi sepenuhnya mendukung pengubahan ukuran.
Implementasi
Aktivitas yang tidak dapat diubah ukurannya dengan orientasi atau rasio aspek tetap dipanggil
mode kompatibilitas ukuran (SCM) dalam kode. Kondisi ini didefinisikan dalam
ActivityRecord#shouldUseSizeCompatMode()
. Ketika aktivitas SCM
diluncurkan, konfigurasi terkait layar (seperti ukuran atau kepadatan)
dalam konfigurasi penggantian yang diminta, sehingga aktivitas tidak lagi bergantung pada
pada konfigurasi tampilan saat ini.
Jika aktivitas SCM tidak dapat mengisi seluruh layar, aktivitas itu akan ditempatkan di atas dan
ke tengah secara horizontal. Batas aktivitas dihitung dengan
AppWindowToken#calculateCompatBoundsTransformation()
.
Ketika aktivitas SCM menggunakan konfigurasi layar yang berbeda dari
(misalnya, tampilan diubah ukurannya, atau aktivitas dipindahkan ke
display), ActivityRecord#inSizeCompatMode()
bernilai benar (true) dan
SizeCompatModeActivityController
(di UI Sistem) menerima
untuk menampilkan tombol mulai ulang proses.
Ukuran layar dan rasio aspek
Android 10 memberikan dukungan untuk rasio aspek baru
dari layar panjang dan tipis dengan rasio tinggi hingga 1:1. Aplikasi dapat menentukan
ApplicationInfo#maxAspectRatio
dan ApplicationInfo#minAspectRatio
layar tempat keduanya
tidak bisa ditangani.
Gambar 1. Contoh rasio aplikasi yang didukung di Android 10
Implementasi perangkat dapat memiliki
tampilan sekunder dengan ukuran dan
resolusi yang lebih kecil dari yang dibutuhkan oleh Android 9, dan yang lebih rendah (minimal 2.5
lebar atau tinggi inci, minimum 320 DP untuk smallestScreenWidth
),
tetapi hanya aktivitas yang memilih untuk mendukung layar kecil ini yang dapat ditempatkan
di sana.
Aplikasi dapat memilih untuk ikut serta dengan menyatakan ukuran minimum yang didukung yang lebih kecil dari
atau sama dengan ukuran tampilan target. Gunakan android:minHeight
dan
atribut tata letak aktivitas android:minWidth
di
AndroidManifest untuk melakukannya.
Kebijakan display
Android 10 memisahkan dan memindahkan tampilan tertentu
kebijakan dari implementasi WindowManagerPolicy
default di
PhoneWindowManager
ke class per-tampilan, seperti:
- Status dan rotasi tampilan
- Beberapa pelacakan peristiwa tombol dan gerakan
- UI sistem dan jendela dekorasi
Di Android 9 (dan yang lebih lama), class PhoneWindowManager
menangani
kebijakan tampilan, status dan setelan, rotasi, bingkai jendela dekorasi
pelacakan, dan banyak lagi. Android 10 memindahkan sebagian besar
class DisplayPolicy
, kecuali untuk pelacakan rotasi, yang memiliki
telah dipindahkan ke DisplayRotation
.
Setelan jendela tampilan
Di Android 10, konfigurasi per tampilan yang dapat dikonfigurasi pengaturan windowing telah diperluas untuk mencakup:
- Mode jendela tampilan default
- Pemindaian berlebih pada nilai
- Mode rotasi dan rotasi pengguna
- Mode ukuran, kepadatan, dan penskalaan paksa
- Mode penghapusan konten (saat layar dihapus)
- Dukungan untuk dekorasi sistem dan IME
Class DisplayWindowSettings
berisi setelan untuk objek ini
lainnya. Tabel disimpan ke disk dalam partisi /data
dalam
display_settings.xml
setiap kali setelan diubah. Sebagai
detail, lihat DisplayWindowSettings.AtomicFileStorage
dan
DisplayWindowSettings#writeSettings()
. Produsen perangkat dapat
memberikan nilai default dalam display_settings.xml
untuk perangkatnya
konfigurasi Anda. Namun, karena file disimpan di /data
,
logika tambahan mungkin diperlukan untuk memulihkan file jika dihapus dengan penghapusan total.
Secara default, Android 10 menggunakan
DisplayInfo#uniqueId
sebagai ID untuk tampilan saat mempertahankan
pengaturan. uniqueId
harus diisi untuk semua layar. Di beberapa
selain itu, lebih stabil untuk
tampilan fisik dan jaringan. Dimungkinkan juga untuk
menggunakan porta tampilan fisik sebagai
pengenal, yang dapat diatur dalam
DisplayWindowSettings#mIdentifier
. Pada setiap penulisan, semua setelan
ditulis sehingga aman untuk memperbarui kunci yang
digunakan untuk entri tampilan di
Storage. Untuk mengetahui detailnya, lihat
ID tampilan statis.
Setelan disimpan di direktori /data
untuk histori
alasan. Awalnya, setelan ini digunakan untuk mempertahankan setelan yang ditetapkan pengguna, seperti
rotasi layar.
ID tampilan statis
Android 9 (dan yang lebih rendah) tidak menyediakan ID yang stabil untuk tampilan di
Google Workspace for Education. Ketika {i>display<i}
ditambahkan ke sistem,
Display#mDisplayId
atau DisplayInfo#displayId
sebelumnya adalah
untuk tampilan itu dengan menambahkan penghitung statis. Jika sistem
menambahkan dan menghapus tampilan yang sama, menghasilkan ID yang berbeda.
Jika perangkat memiliki beberapa
layar yang tersedia dari {i>booting<i}, layar itu bisa
diberi ID yang berbeda, tergantung pada waktunya. Meskipun Android 9 (dan
sebelumnya) menyertakan DisplayInfo#uniqueId
, baris tersebut tidak cukup berisi
informasi untuk membedakan antarlayar karena tampilan fisik
diidentifikasi sebagai local:0
atau local:1
, untuk mewakili
layar bawaan dan eksternal.
DisplayInfo#uniqueId
perubahan Android 10
untuk menambahkan ID yang stabil dan untuk
membedakan antara alamat lokal, jaringan, dan
tampilan virtual.
Jenis tampilan | Format |
---|---|
Lokal | local:<stable-id> |
Jaringan | network:<mac-address> |
Virtual | virtual:<package-name-and-name> |
Selain update pada uniqueId
,
DisplayInfo.address
berisi DisplayAddress
,
ID tampilan yang stabil meskipun telah dimulai ulang. Di Android
10, DisplayAddress
mendukung fisik
dan layar jaringan. DisplayAddress.Physical
berisi stabil
ID tampilan (sama seperti di uniqueId
) dan dapat dibuat dengan
DisplayAddress#fromPhysicalDisplayId()
.
Android 10 juga menyediakan metode yang mudah untuk
informasi porta (Physical#getPort()
). Metode ini dapat digunakan di
kerangka kerja untuk mengidentifikasi
layar secara statis. Misalnya, DHCP digunakan di
DisplayWindowSettings
). DisplayAddress.Network
berisi alamat MAC dan dapat dibuat dengan
DisplayAddress#fromMacAddress()
.
Penambahan ini memungkinkan produsen perangkat mengidentifikasi layar secara statis
penyiapan multi-tampilan dan untuk mengonfigurasi berbagai setelan dan fitur sistem
menggunakan ID tampilan statis, seperti porta untuk tampilan fisik. Ini
metode tersembunyi dan hanya
dimaksudkan untuk digunakan di dalam
system_server
.
Dengan ID tampilan HWC (yang bisa buram dan tidak selalu stabil), ini
mengembalikan nomor port 8-bit (khusus platform) yang mengidentifikasi
konektor fisik untuk output tampilan, serta blob EDID layar.
SurfaceFlinger mengekstrak informasi produsen atau model dari EDID ke
menghasilkan ID tampilan 64-bit stabil yang diekspos ke framework. Jika metode ini
tidak didukung atau mengalami {i>error<i}, SurfaceFlinger
kembali ke mode MD lama,
di mana DisplayInfo#address
adalah null dan
DisplayInfo#uniqueId
adalah hard code, seperti yang dijelaskan di atas.
Untuk memverifikasi bahwa fitur ini didukung, jalankan:
$ 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"
Menggunakan lebih dari dua layar
Di Android 9 (dan yang lebih rendah), SurfaceFlinger dan DisplayManagerService
mengasumsikan adanya maksimal dua layar fisik dengan ID hard code 0
dan 1.
Mulai Android 10, SurfaceFlinger dapat memanfaatkan Hardware Composer (HWC) API untuk menghasilkan ID tampilan yang stabil, yang memungkinkannya mengelola jumlah tampilan fisik yang berubah-ubah. Untuk mempelajari lebih lanjut, lihat ID tampilan statis.
Framework ini dapat mencari token IBinder
untuk
ditampilkan melalui SurfaceControl#getPhysicalDisplayToken
setelah mendapatkan
ID tampilan 64-bit dari SurfaceControl#getPhysicalDisplayIds
atau
dari peristiwa hotplug DisplayEventReceiver
.
Di Android 10 (dan yang lebih lama), tampilan internal utama adalah
TYPE_INTERNAL
dan semua tampilan sekunder ditandai sebagai TYPE_EXTERNAL
terlepas dari jenis koneksi. Oleh karena itu, tampilan internal tambahan dianggap sebagai eksternal.
Sebagai solusinya, kode khusus perangkat
dapat membuat asumsi tentang
DisplayAddress.Physical#getPort
jika HWC diketahui dan alokasi port
logika bisa diprediksi.
Batasan ini dihapus di Android 11 (dan yang lebih baru).
- Di Android 11, tampilan pertama yang dilaporkan selama booting adalah layar utama. Jenis koneksi (internal versus eksternal) tidak relevan. Namun, tetap benar bahwa layar utama tidak dapat diputus dan mengikuti dalam praktiknya harus berupa tampilan internal. Perlu diperhatikan bahwa beberapa ponsel foldable memiliki tampilan internal.
- Layar sekunder dikategorikan dengan benar sebagai
Display.TYPE_INTERNAL
atauDisplay.TYPE_EXTERNAL
(sebelumnya dikenal sebagaiDisplay.TYPE_BUILT_IN
danDisplay.TYPE_HDMI
) bergantung pada jenis koneksinya.
Implementasi
Di Android 9 dan yang lebih rendah, layar
diidentifikasi oleh ID 32-bit,
dengan 0 adalah tampilan internal, 1 adalah layar eksternal, [2, INT32_MAX]
adalah layar virtual HWC, dan -1 mewakili tampilan yang tidak valid atau tampilan virtual non-HWC.
Mulai Android 10, layar akan diberi status stabil
dan ID persisten, yang memungkinkan SurfaceFlinger dan DisplayManagerService
untuk melacak lebih dari dua layar dan mengenali tampilan yang sebelumnya terlihat. Jika HWC
mendukung IComposerClient.getDisplayIdentificationData
dan menyediakan tampilan
data identifikasi, SurfaceFlinger mengurai struktur EDID dan mengalokasikan
ID tampilan 64-bit untuk tampilan fisik dan virtual HWC. ID tersebut dinyatakan menggunakan
jenis opsi, dengan nilai null mewakili tampilan yang tidak valid atau virtual non-HWC
tampilan. Tanpa dukungan HWC, SurfaceFlinger kembali ke perilaku lama dengan
hampir dua layar fisik.
Fokus per-tampilan
Untuk mendukung beberapa sumber input yang menargetkan setiap layar secara bersamaan Android 10 dapat dikonfigurasi untuk mendukung banyak jendela yang terfokus, maksimal satu per-tampilan. Ini hanya ditujukan bagi pengguna jenis perangkat ketika beberapa pengguna berinteraksi dengan perangkat yang sama secara waktu dan menggunakan metode input atau perangkat yang berbeda, seperti Android Otomotif.
Sebaiknya fitur ini tidak diaktifkan untuk perangkat biasa, termasuk perangkat multilayar atau yang digunakan seperti desktop pengalaman yang lancar bagi developer. Hal ini utamanya disebabkan oleh masalah keamanan yang mungkin menyebabkan pengguna untuk bertanya-tanya jendela mana yang memiliki fokus input.
Bayangkan pengguna yang memasukkan informasi aman ke isian {i>input <i}teks, mungkin masuk ke aplikasi perbankan atau memasukkan teks yang berisi tidak akurat atau tidak sesuai. Aplikasi berbahaya dapat membuat tampilan luar layar virtual dengan yang digunakan untuk menjalankan aktivitas, juga dengan isian {i>input <i}teks. Sah dan aktivitas berbahaya memiliki fokus dan keduanya menampilkan indikator input aktif (kursor berkedip).
Namun, karena {i>input<i} dari {i>keyboard<i} (perangkat keras atau perangkat lunak) dimasukkan ke dalam hanya aktivitas teratas (aplikasi yang terakhir diluncurkan), dengan membuat tampilan virtual tersembunyi, aplikasi berbahaya dapat mengambil input pengguna, bahkan saat menggunakan {i>keyboard<i} virtual pada layar perangkat utama.
Gunakan com.android.internal.R.bool.config_perDisplayFocusEnabled
untuk menyetel fokus per-tampilan.
Kompatibilitas
Masalah: Di Android 9 dan yang lebih lama, maksimal satu jendela di fokus pada satu waktu.
Solusi: Dalam kasus yang jarang terjadi, saat dua jendela dari proses yang sama akan difokuskan, sistem memberikan fokus hanya ke jendela yang lebih tinggi dalam urutan Z. Pembatasan ini dihapus untuk aplikasi yang menargetkan Android 10, saat ini diharapkan bisa mendukung beberapa jendela yang difokuskan secara bersamaan.
Implementasi
WindowManagerService#mPerDisplayFocusEnabled
mengontrol
ketersediaan fitur ini. Setelah ActivityManager
,
ActivityDisplay#getFocusedStack()
kini digunakan sebagai pengganti
pelacakan data dalam variabel. ActivityDisplay#getFocusedStack()
menentukan fokus berdasarkan urutan Z daripada
meng-{i>cache<i} nilai. Ini agar
hanya satu sumber, yaitu WindowManager, perlu melacak aktivitas urutan Z.
ActivityStackSupervisor#getTopDisplayFocusedStack()
mengambil
pendekatan serupa untuk kasus tersebut ketika {i>stack <i}paling fokus dalam sistem
harus diidentifikasi. Tumpukan dilalui dari atas ke bawah, untuk mencari
tumpukan pertama yang memenuhi syarat.
InputDispatcher
kini dapat memiliki beberapa jendela yang difokuskan
(satu per tampilan). Jika peristiwa input khusus untuk tampilan, peristiwa itu dikirim
ke jendela yang difokuskan dalam tampilan yang sesuai. Jika tidak, dikirimkan
ke jendela yang difokuskan pada tampilan yang difokuskan, yang merupakan tampilan yang
yang terakhir berinteraksi.
Lihat InputDispatcher::mFocusedWindowHandlesByDisplay
dan
InputDispatcher::setFocusedDisplay()
. Aplikasi yang difokuskan juga akan diupdate
secara terpisah di InputManagerService melalui
NativeInputManager::setFocusedApplication()
.
Di WindowManager
, jendela yang difokuskan juga dilacak secara terpisah.
Lihat DisplayContent#mCurrentFocus
dan
DisplayContent#mFocusedApp
dan penggunaannya masing-masing. Fokus terkait
metode pelacakan dan pembaruan telah dipindahkan dari
WindowManagerService
hingga DisplayContent
.