Merge "DO NOT MERGE Allow pinEntry field to be outside pin_container" into sc-v2-dev
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 5c9da0bc..ebc62f5 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -688,6 +688,7 @@
ctor public AttributionSource(int, @Nullable String, @Nullable String);
ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder);
ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set<java.lang.String>, @Nullable android.content.AttributionSource);
+ method public void enforceCallingPid();
}
public final class AutofillOptions implements android.os.Parcelable {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3553748..b949ed9 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3103,11 +3103,18 @@
}
}
- /** @hide */
- public void resetNewUserDisclaimer() {
+ /**
+ * Acknoledges that the new managed user disclaimer was viewed by the (human) user
+ * so that {@link #ACTION_SHOW_NEW_USER_DISCLAIMER broadcast} is not sent again the next time
+ * this user is switched to.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public void acknowledgeNewUserDisclaimer() {
if (mService != null) {
try {
- mService.resetNewUserDisclaimer();
+ mService.acknowledgeNewUserDisclaimer();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -5673,7 +5680,7 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_SHOW_NEW_USER_DISCLAIMER =
- "android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER";
+ "android.app.action.SHOW_NEW_USER_DISCLAIMER";
/**
* Widgets are enabled in keyguard
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7c7478bd..a2863bd 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -264,7 +264,7 @@
int getLogoutUserId();
void clearLogoutUser();
List<UserHandle> getSecondaryUsers(in ComponentName who);
- void resetNewUserDisclaimer();
+ void acknowledgeNewUserDisclaimer();
void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName);
int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent);
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index bdb7900..2f61fee 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -154,8 +154,8 @@
this(AttributionSourceState.CREATOR.createFromParcel(in));
// Since we just unpacked this object as part of it transiting a Binder
- // call, this is the perfect time to enforce that its UID can be trusted
- enforceCallingUid();
+ // call, this is the perfect time to enforce that its UID and PID can be trusted
+ enforceCallingUidAndPid();
}
/** @hide */
@@ -226,13 +226,24 @@
}
/**
+ * If you are handling an IPC and you don't trust the caller you need to validate whether the
+ * attribution source is one for the calling app to prevent the caller to pass you a source from
+ * another app without including themselves in the attribution chain.
+ *
+ * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
+ */
+ private void enforceCallingUidAndPid() {
+ enforceCallingUid();
+ enforceCallingPid();
+ }
+
+ /**
* If you are handling an IPC and you don't trust the caller you need to validate
* whether the attribution source is one for the calling app to prevent the caller
* to pass you a source from another app without including themselves in the
* attribution chain.
*
- * @throws SecurityException if the attribution source cannot be trusted to be
- * from the caller.
+ * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
*/
public void enforceCallingUid() {
if (!checkCallingUid()) {
@@ -261,6 +272,33 @@
return true;
}
+ /**
+ * Validate that the pid being claimed for the calling app is not spoofed
+ *
+ * @throws SecurityException if the attribution source cannot be trusted to be from the caller.
+ * @hide
+ */
+ @TestApi
+ public void enforceCallingPid() {
+ if (!checkCallingPid()) {
+ throw new SecurityException("Calling pid: " + Binder.getCallingPid()
+ + " doesn't match source pid: " + mAttributionSourceState.pid);
+ }
+ }
+
+ /**
+ * Validate that the pid being claimed for the calling app is not spoofed
+ *
+ * @return if the attribution source cannot be trusted to be from the caller.
+ */
+ private boolean checkCallingPid() {
+ final int callingPid = Binder.getCallingPid();
+ if (mAttributionSourceState.pid != -1 && callingPid != mAttributionSourceState.pid) {
+ return false;
+ }
+ return true;
+ }
+
@Override
public String toString() {
if (Build.IS_DEBUGGABLE) {
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index a8a5837..0f9acad 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -739,7 +739,7 @@
* {@link #startMainActivity(ComponentName, UserHandle, Rect, Bundle)}.
*
* @param component The ComponentName of the activity to launch
- * @param startActivityOptions Options to pass to startActivity
+ * @param startActivityOptions This parameter is no longer supported
* @param user The UserHandle of the profile
* @hide
*/
@@ -751,7 +751,8 @@
Log.i(TAG, "GetMainActivityLaunchIntent " + component + " " + user);
}
try {
- return mService.getActivityLaunchIntent(component, startActivityOptions, user);
+ // due to b/209607104, startActivityOptions will be ignored
+ return mService.getActivityLaunchIntent(component, null /* opts */, user);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -846,7 +847,7 @@
*
* @param packageName The packageName of the shortcut
* @param shortcutId The id of the shortcut
- * @param opts Options to pass to the PendingIntent
+ * @param opts This parameter is no longer supported
* @param user The UserHandle of the profile
*/
@Nullable
@@ -858,8 +859,9 @@
Log.i(TAG, "GetShortcutIntent " + packageName + "/" + shortcutId + " " + user);
}
try {
+ // due to b/209607104, opts will be ignored
return mService.getShortcutIntent(
- mContext.getPackageName(), packageName, shortcutId, opts, user);
+ mContext.getPackageName(), packageName, shortcutId, null /* opts */, user);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java
index 7714dd8..243f801 100644
--- a/core/java/android/debug/AdbManager.java
+++ b/core/java/android/debug/AdbManager.java
@@ -38,6 +38,7 @@
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_STATE_CHANGED_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_STATUS";
@@ -46,6 +47,7 @@
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_PAIRED_DEVICES_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES";
@@ -59,6 +61,7 @@
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_PAIRING_RESULT_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT";
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 2d1f17a..a0ec48b 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -297,12 +297,12 @@
} else {
mTextClassification = null;
}
- final SelectionModifierCursorController controller = mEditor.getSelectionController();
- if (controller != null
- && (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
- controller.show();
- }
if (mEditor.startActionModeInternal(actionMode)) {
+ final SelectionModifierCursorController controller = mEditor.getSelectionController();
+ if (controller != null
+ && (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
+ controller.show();
+ }
if (result != null) {
switch (actionMode) {
case Editor.TextActionMode.SELECTION:
diff --git a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
index ce2d229..33209e1 100644
--- a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
+++ b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
@@ -16,6 +16,8 @@
package com.android.internal.app;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -27,6 +29,7 @@
import android.util.Log;
import android.view.View;
import android.widget.TextView;
+
import com.android.internal.R;
/**
@@ -48,6 +51,7 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
final Intent intent = getIntent();
mPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f525315..2ad836e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -703,7 +703,7 @@
<protected-broadcast android:name="android.scheduling.action.REBOOT_READY" />
<protected-broadcast android:name="android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED" />
<protected-broadcast android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
- <protected-broadcast android:name="android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER" />
+ <protected-broadcast android:name="android.app.action.SHOW_NEW_USER_DISCLAIMER" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index bc324f4..0c66323 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -349,7 +349,7 @@
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"تنفيذ إيماءات"</string>
<string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"يمكن النقر والتمرير بسرعة والتصغير أو التكبير بإصبعين وتنفيذ إيماءات أخرى."</string>
<string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"إيماءات بصمات الإصبع:"</string>
- <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"يمكن أن تلتقط الإيماءات التي تم تنفيذها على جهاز استشعار بصمة الإصبع في الجهاز."</string>
+ <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"يمكن أن تلتقط الإيماءات من أداة استشعار بصمة الإصبع في الجهاز."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"أخذ لقطة شاشة"</string>
<string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"يمكن أخذ لقطة شاشة."</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"إيقاف شريط الحالة أو تعديله"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index b9b3208..f518997 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -78,7 +78,7 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"ID pozivaoca podrazumevano nije ograničen. Sledeći poziv: Nije ograničen."</string>
<string name="serviceNotProvisioned" msgid="8289333510236766193">"Usluga nije dobavljena."</string>
<string name="CLIRPermanent" msgid="166443681876381118">"Ne možete da promenite podešavanje ID-a korisnika."</string>
- <string name="RestrictedOnDataTitle" msgid="1500576417268169774">"Nema usluge prenosa podataka preko mobilnog operatera"</string>
+ <string name="RestrictedOnDataTitle" msgid="1500576417268169774">"Nema usluge mobilnih podataka"</string>
<string name="RestrictedOnEmergencyTitle" msgid="2852916906106191866">"Hitni pozivi nisu dostupni"</string>
<string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"Nema glasovne usluge"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"Nema glasovne usluge ni hitnih poziva"</string>
@@ -2183,7 +2183,7 @@
<string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Obaveštenja"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Brza podešavanja"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Dijalog napajanja"</string>
- <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključani ekran"</string>
+ <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključavanje ekrana"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimak ekrana"</string>
<string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"Prečica za pristupačnost na ekranu"</string>
<string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"Alatka za biranje prečica za pristupačnost na ekranu"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 6473ae4..2cb8c72 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -339,7 +339,7 @@
<string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Gestos del sensor de huellas dactilares"</string>
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Capturará los gestos que se hacen en el sensor de huellas dactilares del dispositivo."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Tomar captura de pantalla"</string>
- <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede tomar una captura de la pantalla."</string>
+ <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Puede tomar capturas de pantalla."</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"desactivar o modificar la barra de estado"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Permite que la aplicación inhabilite la barra de estado o que agregue y elimine íconos del sistema."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"aparecer en la barra de estado"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index c502b80..03901c5 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1335,7 +1335,7 @@
<string name="select_character" msgid="3352797107930786979">"درج نویسه"</string>
<string name="sms_control_title" msgid="4748684259903148341">"درحال ارسال پیامکها"</string>
<string name="sms_control_message" msgid="6574313876316388239">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> درحال ارسال تعداد زیادی پیامک است. آیا اجازه میدهید این برنامه همچنان پیامک ارسال کند؟"</string>
- <string name="sms_control_yes" msgid="4858845109269524622">"مجاز بودن"</string>
+ <string name="sms_control_yes" msgid="4858845109269524622">"مجاز است"</string>
<string name="sms_control_no" msgid="4845717880040355570">"مجاز نبودن"</string>
<string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> مایل است پیامی به <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> ارسال کند."</string>
<string name="sms_short_code_details" msgid="2723725738333388351">"این مورد "<b>"شاید هزینهای"</b>" را به حساب دستگاه همراهتان بگذارد."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 5031ec7..1ba7de6 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -271,7 +271,7 @@
<string name="global_action_settings" msgid="4671878836947494217">"Paramètres"</string>
<string name="global_action_assist" msgid="2517047220311505805">"Assistance"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"Assistance vocale"</string>
- <string name="global_action_lockdown" msgid="2475471405907902963">"Verrouillé"</string>
+ <string name="global_action_lockdown" msgid="2475471405907902963">"Verrouiller"</string>
<string name="status_bar_notification_info_overflow" msgid="3330152558746563475">">999"</string>
<string name="notification_hidden_text" msgid="2835519769868187223">"Nouvelle notification"</string>
<string name="notification_channel_virtual_keyboard" msgid="6465975799223304567">"Clavier virtuel"</string>
@@ -2016,7 +2016,7 @@
<string name="app_category_image" msgid="7307840291864213007">"Photos et images"</string>
<string name="app_category_social" msgid="2278269325488344054">"Réseaux sociaux et communication"</string>
<string name="app_category_news" msgid="1172762719574964544">"Actualités et magazines"</string>
- <string name="app_category_maps" msgid="6395725487922533156">"Plans et navigation"</string>
+ <string name="app_category_maps" msgid="6395725487922533156">"Cartes et navigation"</string>
<string name="app_category_productivity" msgid="1844422703029557883">"Productivité"</string>
<string name="app_category_accessibility" msgid="6643521607848547683">"Accessibilité"</string>
<string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"Mémoire de l\'appareil"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index ae73ee1..2ff66de 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -619,7 +619,7 @@
<string name="face_sensor_privacy_enabled" msgid="7407126963510598508">"Para usar o desbloqueo facial, activa "<b>"Acceso á cámara"</b>" en Configuración > Privacidade"</string>
<string name="fingerprint_setup_notification_title" msgid="2002630611398849495">"Configura máis maneiras de desbloquear o dispositivo"</string>
<string name="fingerprint_setup_notification_content" msgid="205578121848324852">"Toca para engadir unha impresión dixital"</string>
- <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Desbloqueo mediante impresión dixital"</string>
+ <string name="fingerprint_recalibrate_notification_name" msgid="1414578431898579354">"Desbloqueo dactilar"</string>
<string name="fingerprint_recalibrate_notification_title" msgid="2406561052064558497">"Non se puido usar o sensor de impresión dixital"</string>
<string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visita un provedor de reparacións."</string>
<string name="face_acquired_insufficient" msgid="2150805835949162453">"Sen datos faciais exactos. Téntao de novo."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e8390da..01c94ab 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -533,11 +533,11 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul tablet e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Consente all\'app di visualizzare la configurazione del Bluetooth del dispositivo Android TV, nonché di stabilire e accettare connessioni con dispositivi accoppiati."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul telefono e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
- <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Rilevamento/accopp. dispositivi Bluetooth vicini"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Rilevamento e accoppiamento di dispositivi Bluetooth vicini"</string>
<string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Consente all\'app di rilevare e accoppiare dispositivi Bluetooth nelle vicinanze"</string>
<string name="permlab_bluetooth_connect" msgid="6657463246355003528">"Connessione a dispositivi Bluetooth accoppiati"</string>
<string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Consente all\'app di connettersi ai dispositivi Bluetooth accoppiati"</string>
- <string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"trasmettere annunci a dispositivi Bluetooth vicini"</string>
+ <string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"Trasmissione di annunci a dispositivi Bluetooth vicini"</string>
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Consente all\'app di trasmettere annunci ai dispositivi Bluetooth nelle vicinanze"</string>
<string name="permlab_uwb_ranging" msgid="8141915781475770665">"Possibilità di stabilire la posizione relativa tra dispositivi a banda ultralarga nelle vicinanze"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"Consenti all\'app di stabilire la posizione relativa tra dispositivi a banda ultralarga nelle vicinanze"</string>
@@ -671,9 +671,9 @@
<string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Consente a un\'applicazione di modificare le impostazioni di sincronizzazione per un account. Ad esempio, può servire per attivare la sincronizzazione dell\'applicazione Persone con un account."</string>
<string name="permlab_readSyncStats" msgid="3747407238320105332">"lettura statistiche di sincronizz."</string>
<string name="permdesc_readSyncStats" msgid="3867809926567379434">"Consente a un\'applicazione di leggere le statistiche di sincronizzazione per un account, incluse la cronologia degli eventi di sincronizzazione e la quantità di dati sincronizzati."</string>
- <string name="permlab_sdcardRead" msgid="5791467020950064920">"lettura dei contenuti dell\'archivio condiviso"</string>
+ <string name="permlab_sdcardRead" msgid="5791467020950064920">"Lettura dei contenuti dell\'archivio condiviso"</string>
<string name="permdesc_sdcardRead" msgid="6872973242228240382">"Consente all\'app di leggere i contenuti del tuo archivio condiviso."</string>
- <string name="permlab_sdcardWrite" msgid="4863021819671416668">"modifica/eliminazione dei contenuti dell\'archivio condiviso"</string>
+ <string name="permlab_sdcardWrite" msgid="4863021819671416668">"Modifica/eliminazione dei contenuti dell\'archivio condiviso"</string>
<string name="permdesc_sdcardWrite" msgid="8376047679331387102">"Consente all\'app di modificare i contenuti del tuo archivio condiviso."</string>
<string name="permlab_use_sip" msgid="8250774565189337477">"invio/ricezione di chiamate SIP"</string>
<string name="permdesc_use_sip" msgid="3590270893253204451">"Consente all\'app di effettuare e ricevere chiamate SIP."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 004f3d1..7d2b667 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -30,7 +30,7 @@
<string name="untitled" msgid="3381766946944136678">"<新規>"</string>
<string name="emptyPhoneNumber" msgid="5812172618020360048">"(電話番号なし)"</string>
<string name="unknownName" msgid="7078697621109055330">"不明"</string>
- <string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"ボイスメール"</string>
+ <string name="defaultVoiceMailAlphaTag" msgid="2190754495304236490">"留守番電話"</string>
<string name="defaultMsisdnAlphaTag" msgid="2285034592902077488">"MSISDN1"</string>
<string name="mmiError" msgid="2862759606579822246">"接続に問題があるか、MMIコードが正しくありません。"</string>
<string name="mmiFdnError" msgid="3975490266767565852">"発信番号制限で指定された番号に対してのみ操作できます。"</string>
@@ -92,7 +92,7 @@
<string name="notification_channel_emergency_callback" msgid="54074839059123159">"緊急通報待機モード"</string>
<string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"モバイルデータのステータス"</string>
<string name="notification_channel_sms" msgid="1243384981025535724">"SMS メッセージ"</string>
- <string name="notification_channel_voice_mail" msgid="8457433203106654172">"ボイスメール メッセージ"</string>
+ <string name="notification_channel_voice_mail" msgid="8457433203106654172">"留守番電話メッセージ"</string>
<string name="notification_channel_wfc" msgid="9048240466765169038">"Wi-Fi 通話"</string>
<string name="notification_channel_sim" msgid="5098802350325677490">"SIM のステータス"</string>
<string name="notification_channel_sim_high_prio" msgid="642361929452850928">"高優先度: SIM のステータス"</string>
@@ -1019,8 +1019,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"モバイル デバイスに保存されているブラウザの履歴やブックマークの変更をアプリに許可します。これにより、アプリがブラウザデータを消去または変更できるようになる可能性があります。注: この許可は、サードパーティブラウザまたはウェブブラウジング機能を備えたその他のアプリでは適用されない場合があります。"</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"アラームの設定"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"インストール済みアラームアプリのアラームを設定することをアプリに許可します。この機能が実装されていないアラームアプリもあります。"</string>
- <string name="permlab_addVoicemail" msgid="4770245808840814471">"ボイスメールの追加"</string>
- <string name="permdesc_addVoicemail" msgid="5470312139820074324">"ボイスメール受信トレイにメッセージを追加することをアプリに許可します。"</string>
+ <string name="permlab_addVoicemail" msgid="4770245808840814471">"留守番電話の追加"</string>
+ <string name="permdesc_addVoicemail" msgid="5470312139820074324">"留守番電話受信トレイにメッセージを追加することをアプリに許可します。"</string>
<string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"ブラウザの現在地情報に対する権限の変更"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"ブラウザの現在地情報に対する権限の変更をアプリに許可します。この許可を悪意のあるアプリに利用されると、任意のウェブサイトに現在地情報が送信される恐れがあります。"</string>
<string name="save_password_message" msgid="2146409467245462965">"このパスワードをブラウザで保存しますか?"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index b0095c3..f784f1f 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -450,9 +450,9 @@
<string name="permdesc_recordBackgroundAudio" msgid="1992623135737407516">"Бул колдонмо каалаган убакта микрофон менен аудио файлдарды жаздыра алат."</string>
<string name="permlab_sim_communication" msgid="176788115994050692">"SIM-картага буйруктарды жөнөтүү"</string>
<string name="permdesc_sim_communication" msgid="4179799296415957960">"Колдонмого SIM-картага буйруктарды жөнөтүү мүмкүнчүлүгүн берет. Бул абдан кооптуу."</string>
- <string name="permlab_activityRecognition" msgid="1782303296053990884">"кыймыл-аракетти аныктоо"</string>
+ <string name="permlab_activityRecognition" msgid="1782303296053990884">"Кыймыл-аракетти аныктоо"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"Бул колдонмо кыймыл-аракетиңизди аныктап турат."</string>
- <string name="permlab_camera" msgid="6320282492904119413">"сүрөт жана видео тартуу"</string>
+ <string name="permlab_camera" msgid="6320282492904119413">"Сүрөт жана видео тартуу"</string>
<string name="permdesc_camera" msgid="5240801376168647151">"Бул колдонмо иштеп жатканда камера менен сүрөт же видеолорду тарта алат."</string>
<string name="permlab_backgroundCamera" msgid="7549917926079731681">"Фондо сүрөткө жана видеого тартат"</string>
<string name="permdesc_backgroundCamera" msgid="1615291686191138250">"Бул колдонмо каалаган убакта камера менен сүрөт же видеолорду тарта алат."</string>
@@ -533,13 +533,13 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Колдонмого планшеттин Bluetooth конфигурацияларын көрүү, жупталган түзмөктөр менен байланыш түзүү жана кабыл алуу уруксатын берет."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV түзмөгүңүздөгү Bluetooth конфигурациясын көрүп, жупташтырылган түзмөктөргө туташууга жана туташуу сурамын кабыл алууга колдонмого уруксат берет."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Колдонмого телефондун Bluetooth конфигурацияларын көрүү, жупташкан түзмөктөр менен туташуу түзүү жана кабыл алуу уруксатын берет."</string>
- <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"жакын жердеги Bluetooth түзмөктөрүн аныктоо жана жупташтыруу"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Жакын жердеги Bluetooth түзмөктөрүн таап, туташуу"</string>
<string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Колдонмого жакын жердеги Bluetooth түзмөктөрүн аныктап, жупташтырууга уруксат берет"</string>
- <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"жупташтырылган Bluetooth түзмөктөрү"</string>
- <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Колдонмого жупташтырылган Bluetooth түзмөктөрү менен байланышууга уруксат берет"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"Туташып турган Bluetooth түзмөктөрүнө байланышуу"</string>
+ <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Колдонмого туташкан Bluetooth түзмөктөрүнө байланышканга уруксат берет"</string>
<string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"жакын жердеги Bluetooth түзмөктөрүнө жарнамалоо"</string>
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Колдонмого жакын жердеги Bluetooth түзмөктөрүнө жарнама көрсөтүүгө мүмкүндүк берет"</string>
- <string name="permlab_uwb_ranging" msgid="8141915781475770665">"кең тилкелүү тармак аркылуу туташа турган жакын жердеги түзмөктөрдү аныктоо"</string>
+ <string name="permlab_uwb_ranging" msgid="8141915781475770665">"Кең тилкелүү тармак аркылуу туташа турган жакын жердеги түзмөктөрдү аныктоо"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"Колдонмо кең тилкелүү тармак аркылуу туташа турган жакын жердеги түзмөктөрдү аныктай алат"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Тандалган NFC төлөм кызматы жөнүндө маалымат"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Колдонмого катталган жардам же көздөлгөн жерге маршрут сыяктуу тандалган nfc төлөм кызматы жөнүндө маалыматты алууга уруксат берүү."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index fd12a78..f097f63 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1333,7 +1333,7 @@
<!-- no translation found for network_available_sign_in_detailed (7520423801613396556) -->
<skip />
<string name="wifi_no_internet" msgid="1386911698276448061">"Tīklā <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nav piekļuves internetam"</string>
- <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Pieskarieties, lai skatītu iespējas."</string>
+ <string name="wifi_no_internet_detailed" msgid="634938444133558942">"Pieskarieties, lai skatītu opcijas."</string>
<string name="mobile_no_internet" msgid="4014455157529909781">"Mobilajā tīklā nav piekļuves internetam."</string>
<string name="other_networks_no_internet" msgid="6698711684200067033">"Tīklā nav piekļuves internetam."</string>
<string name="private_dns_broken_detailed" msgid="3709388271074611847">"Nevar piekļūt privātam DNS serverim."</string>
@@ -1394,7 +1394,7 @@
<string name="usb_tether_notification_title" msgid="8828527870612663771">"Ieslēgta USB piesaiste"</string>
<string name="usb_midi_notification_title" msgid="7404506788950595557">"Ieslēgts MIDI režīms, izmantojot USB savienojumu"</string>
<string name="usb_accessory_notification_title" msgid="1385394660861956980">"USB piederums ir pievienots"</string>
- <string name="usb_notification_message" msgid="4715163067192110676">"Pieskarieties, lai skatītu citas iespējas."</string>
+ <string name="usb_notification_message" msgid="4715163067192110676">"Pieskarieties, lai skatītu citas opcijas."</string>
<string name="usb_power_notification_message" msgid="7284765627437897702">"Pievienotā ierīce tiek uzlādēta. Pieskarieties, lai skatītu citas opcijas."</string>
<string name="usb_unsupported_audio_accessory_title" msgid="2335775548086533065">"Konstatēts analogs audio piederums"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="1300168007129796621">"Pievienotā ierīce nav saderīga ar šo tālruni. Pieskarieties, lai uzzinātu vairāk."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 52182f5..b6a69e0 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -2020,7 +2020,7 @@
<string name="close_button_text" msgid="10603510034455258">"Zamknij"</string>
<string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
<string name="call_notification_answer_action" msgid="5999246836247132937">"Odbierz"</string>
- <string name="call_notification_answer_video_action" msgid="2086030940195382249">"Film"</string>
+ <string name="call_notification_answer_video_action" msgid="2086030940195382249">"Wideo"</string>
<string name="call_notification_decline_action" msgid="3700345945214000726">"Odrzuć"</string>
<string name="call_notification_hang_up_action" msgid="9130720590159188131">"Rozłącz"</string>
<string name="call_notification_incoming_text" msgid="6143109825406638201">"Połączenie przychodzące"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 648ca00..5f6cceb 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -533,9 +533,9 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que o app acesse a configuração do Bluetooth no tablet, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que o app acesse a configuração do Bluetooth no dispositivo Android TV, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que o app acesse a configuração do Bluetooth no telefone, além de fazer e aceitar conexões com dispositivos pareados."</string>
- <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"descobrir e se parear a disp. Bluetooth por perto"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"descobrir e parear com disp. Bluetooth por perto"</string>
<string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite que o app descubra e se pareie a dispositivos Bluetooth por perto"</string>
- <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conecte-se a dispositivos Bluetooth pareados"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conectar a dispositivos Bluetooth pareados"</string>
<string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite que o app se conecte a dispositivos Bluetooth pareados"</string>
<string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"anunciar em dispositivos Bluetooth por perto"</string>
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Permite que o app seja anunciado em dispositivos Bluetooth por perto"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 648ca00..5f6cceb 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -533,9 +533,9 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Permite que o app acesse a configuração do Bluetooth no tablet, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Permite que o app acesse a configuração do Bluetooth no dispositivo Android TV, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Permite que o app acesse a configuração do Bluetooth no telefone, além de fazer e aceitar conexões com dispositivos pareados."</string>
- <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"descobrir e se parear a disp. Bluetooth por perto"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"descobrir e parear com disp. Bluetooth por perto"</string>
<string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Permite que o app descubra e se pareie a dispositivos Bluetooth por perto"</string>
- <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conecte-se a dispositivos Bluetooth pareados"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"conectar a dispositivos Bluetooth pareados"</string>
<string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Permite que o app se conecte a dispositivos Bluetooth pareados"</string>
<string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"anunciar em dispositivos Bluetooth por perto"</string>
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Permite que o app seja anunciado em dispositivos Bluetooth por perto"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 8020cdd..504fa13 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -345,7 +345,7 @@
<string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Регистрировать жесты на сканере отпечатков пальцев"</string>
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Использовать сканер отпечатков пальцев для дополнительных жестов."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Создавать скриншоты"</string>
- <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Создавать скриншоты экрана."</string>
+ <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Создавать снимки экрана."</string>
<string name="permlab_statusBar" msgid="8798267849526214017">"Отключение/изменение строки состояния"</string>
<string name="permdesc_statusBar" msgid="5809162768651019642">"Приложение сможет отключать строку состояния, а также добавлять и удалять системные значки."</string>
<string name="permlab_statusBarService" msgid="2523421018081437981">"Замена строки состояния"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index cccefdd..5a55b06 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -78,7 +78,7 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"ИД позиваоца подразумевано није ограничен. Следећи позив: Није ограничен."</string>
<string name="serviceNotProvisioned" msgid="8289333510236766193">"Услуга није добављена."</string>
<string name="CLIRPermanent" msgid="166443681876381118">"Не можете да промените подешавање ИД-а корисника."</string>
- <string name="RestrictedOnDataTitle" msgid="1500576417268169774">"Нема услуге преноса података преко мобилног оператера"</string>
+ <string name="RestrictedOnDataTitle" msgid="1500576417268169774">"Нема услуге мобилних података"</string>
<string name="RestrictedOnEmergencyTitle" msgid="2852916906106191866">"Хитни позиви нису доступни"</string>
<string name="RestrictedOnNormalTitle" msgid="7009474589746551737">"Нема гласовне услуге"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="3982069078579103087">"Нема гласовне услуге ни хитних позива"</string>
@@ -2183,7 +2183,7 @@
<string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Обавештења"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Брза подешавања"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Дијалог напајања"</string>
- <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Закључани екран"</string>
+ <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Закључавање екрана"</string>
<string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Снимак екрана"</string>
<string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"Пречица за приступачност на екрану"</string>
<string name="accessibility_system_action_on_screen_a11y_shortcut_chooser_label" msgid="1057878690209817886">"Алатка за бирање пречица за приступачност на екрану"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index cf76440..5e6c79c 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -937,7 +937,7 @@
<string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"అన్లాక్ చేయడానికి, మీ Google ఖాతాతో సైన్ ఇన్ చేయండి."</string>
<string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"వినియోగదారు పేరు (ఈమెయిల్)"</string>
<string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"పాస్వర్డ్"</string>
- <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"సైన్ ఇన్ చేయి"</string>
+ <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"సైన్ ఇన్ చేయండి"</string>
<string name="lockscreen_glogin_invalid_input" msgid="4369219936865697679">"వినియోగదారు పేరు లేదా పాస్వర్డ్ చెల్లదు."</string>
<string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"మీ వినియోగదారు పేరు లేదా పాస్వర్డ్ను మర్చిపోయారా?\n"<b>"google.com/accounts/recovery"</b>"ని సందర్శించండి."</string>
<string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"తనిఖీ చేస్తోంది..."</string>
@@ -1676,7 +1676,7 @@
<string name="kg_login_instructions" msgid="3619844310339066827">"అన్లాక్ చేయడానికి, మీ Google ఖాతాతో సైన్ ఇన్ చేయండి."</string>
<string name="kg_login_username_hint" msgid="1765453775467133251">"వినియోగదారు పేరు (ఈమెయిల్)"</string>
<string name="kg_login_password_hint" msgid="3330530727273164402">"పాస్వర్డ్"</string>
- <string name="kg_login_submit_button" msgid="893611277617096870">"సైన్ ఇన్ చేయి"</string>
+ <string name="kg_login_submit_button" msgid="893611277617096870">"సైన్ ఇన్ చేయండి"</string>
<string name="kg_login_invalid_input" msgid="8292367491901220210">"చెల్లని వినియోగదారు పేరు లేదా పాస్వర్డ్."</string>
<string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"మీ వినియోగదారు పేరు లేదా పాస్వర్డ్ను మర్చిపోయారా?\n"<b>"google.com/accounts/recovery"</b>"ని సందర్శించండి."</string>
<string name="kg_login_checking_password" msgid="4676010303243317253">"ఖాతాను తనిఖీ చేస్తోంది…"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 03b4fb8..9d96f81 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -533,13 +533,13 @@
<string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Ilovaga planshetdagi Bluetooth‘ning sozlamasini ko‘rishga va bog‘langan qurilmalarga ulanish va ulardan ulanish so‘rovlarini qabul qulishga imkon beradi."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Ilovaga Android TV qurilmangizdagi Bluetooth sozlamasini koʻrishga va bogʻlangan qurilmalarga ulanish va ulardan ulanish talablarni qabul qilishga imkon beradi."</string>
<string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Ilovaga telefondagi Bluetooth‘ning sozlamasini ko‘rishga va bog‘langan qurilmalarga ulanish va ulardan ulanish so‘rovlarini qabul qulishga imkon beradi."</string>
- <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Bluetooth qurilmalarini topish va juftlashish"</string>
+ <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"Bluetooth qurilmalarni topish va juftlash"</string>
<string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Ilovaga yaqin-atrofdagi Bluetooth qurilmalarini topish va juftlashish uchun ruxsat beradi"</string>
- <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"juftlangan Bluetooth qurilmalariga ulanish"</string>
+ <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"Juftlangan Bluetooth qurilmalarga ulanish"</string>
<string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Ilovaga juftlangan Bluetooth qurilmalariga ulanish uchun ruxsat beradi"</string>
- <string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"atrofdagi Bluetooth qurilmalariga reklama berish"</string>
+ <string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"Atrofdagi Bluetooth qurilmalarga reklama yuborish"</string>
<string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Ilovaga yaqin-atrofdagi Bluetooth qurilmalariga reklama yuborish imkonini beradi"</string>
- <string name="permlab_uwb_ranging" msgid="8141915781475770665">"yaqin atrofdagi ultra keng polosali qurilmalarining nisbiy joylashishini aniqlash"</string>
+ <string name="permlab_uwb_ranging" msgid="8141915781475770665">"Atrofdagi ultra-keng aloqa kanalli qurilmalarning nisbiy joylashuvini aniqlash"</string>
<string name="permdesc_uwb_ranging" msgid="2519723069604307055">"Ilovaga yaqin atrofdagi ultra keng polosali qurilmalarining nisbiy joylashishini aniqlashga ruxsat beradi"</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"Asosiy NFC toʻlov xizmati haqidagi axborot"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"Bu ilovaga asosiy NFC toʻlov xizmati haqidagi axborotni olish imkonini beradi (masalan, qayd qilingan AID identifikatorlari va marshrutning yakuniy manzili)."</string>
@@ -891,7 +891,7 @@
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Qulfni ochish uchun \"Menyu\"ga bosing."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Qulfni ochish uchun grafik kalitni chizing"</string>
<string name="lockscreen_emergency_call" msgid="7549683825868928636">"Favqulodda chaqiruv"</string>
- <string name="lockscreen_return_to_call" msgid="3156883574692006382">"Qo‘ng‘iroqni qaytarish"</string>
+ <string name="lockscreen_return_to_call" msgid="3156883574692006382">"Chaqiruvga qaytish"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"To‘g‘ri!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Qaytadan urining"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Qaytadan urining"</string>
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 40ef04a..152992c 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -17,6 +17,7 @@
package android.widget;
import static android.widget.espresso.CustomViewActions.longPressAtRelativeCoordinates;
+import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem;
@@ -426,6 +427,41 @@
}
@Test
+ public void testSelectionOnCreateActionModeReturnsFalse() throws Throwable {
+ final String text = "hello world";
+ mActivityRule.runOnUiThread(() -> {
+ final TextView textView = mActivity.findViewById(R.id.textview);
+ textView.setText(text);
+ textView.setCustomSelectionActionModeCallback(
+ new ActionMode.Callback() {
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ return false;
+ }
+
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ }
+ });
+ });
+ mInstrumentation.waitForIdleSync();
+ onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("d")));
+ mInstrumentation.waitForIdleSync();
+ assertNoSelectionHandles();
+ }
+
+ @Test
public void testSelectionRemovedWhenNonselectableTextLosesFocus() throws Throwable {
final TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview);
final int position = (textLink.getStart() + textLink.getEnd()) / 2;
diff --git a/data/etc/car/com.android.car.shell.xml b/data/etc/car/com.android.car.shell.xml
index 992840d..3e57753 100644
--- a/data/etc/car/com.android.car.shell.xml
+++ b/data/etc/car/com.android.car.shell.xml
@@ -37,5 +37,6 @@
<permission name="android.car.permission.USE_CAR_WATCHDOG" />
<permission name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS" />
<permission name="android.car.permission.CONTROL_CAR_WATCHDOG_CONFIG" />
+ <permission name="android.car.permission.USE_CAR_TELEMETRY_SERVICE"/>
</privapp-permissions>
</permissions>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 620c291..14433c2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1724,6 +1724,7 @@
/**
* Changes the expanded state of the stack.
+ * Don't call this directly, call mBubbleData#setExpanded.
*
* @param shouldExpand whether the bubble stack should appear expanded
*/
@@ -1770,7 +1771,7 @@
} else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
mManageEduView.hide();
} else {
- setExpanded(false);
+ mBubbleData.setExpanded(false);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index f0b2716..a201616 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -825,6 +825,10 @@
}
private void fadeExistingPip(boolean show) {
+ if (mLeash == null || !mLeash.isValid()) {
+ Log.w(TAG, "Invalid leash on fadeExistingPip: " + mLeash);
+ return;
+ }
final float alphaStart = show ? 0 : 1;
final float alphaEnd = show ? 1 : 0;
mPipAnimationController
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 07d04aa..dd2b624 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -22,6 +22,6 @@
<string name="profile_name_watch" msgid="576290739483672360">"ساعت"</string>
<string name="confirmation_title" msgid="8455544820286920304">"مجاز کردن <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> برای مدیریت کردن <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_summary" msgid="2059360676631420073">"این برنامه برای مدیریت <xliff:g id="PROFILE_NAME">%1$s</xliff:g> شما لازم است. <xliff:g id="PRIVILEGES_DISCPLAIMER">%2$s</xliff:g>"</string>
- <string name="consent_yes" msgid="8344487259618762872">"مجاز بودن"</string>
+ <string name="consent_yes" msgid="8344487259618762872">"مجاز است"</string>
<string name="consent_no" msgid="2640796915611404382">"مجاز نبودن"</string>
</resources>
diff --git a/packages/PackageInstaller/res/values-es-rUS/strings.xml b/packages/PackageInstaller/res/values-es-rUS/strings.xml
index bdacb64..02bb6f4 100644
--- a/packages/PackageInstaller/res/values-es-rUS/strings.xml
+++ b/packages/PackageInstaller/res/values-es-rUS/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="7488448184431507488">"Instalador del paquete"</string>
+ <string name="app_name" msgid="7488448184431507488">"Instalador de paquetes"</string>
<string name="install" msgid="711829760615509273">"Instalar"</string>
<string name="update" msgid="3932142540719227615">"Actualizar"</string>
<string name="done" msgid="6632441120016885253">"Listo"</string>
diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml
index 33543fd..4e9a599 100644
--- a/packages/PackageInstaller/res/values-te/strings.xml
+++ b/packages/PackageInstaller/res/values-te/strings.xml
@@ -57,7 +57,7 @@
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"మీరు ఈ యాప్ను "<b>"అందరు"</b>" వినియోగదారులకు అన్ఇన్స్టాల్ చేయాలనుకుంటున్నారా? అప్లికేషన్, దాని డేటా పరికరంలోని "<b>"అందరు"</b>" వినియోగదారుల నుండి తీసివేయబడుతుంది."</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"మీరు వినియోగదారు <xliff:g id="USERNAME">%1$s</xliff:g> కోసం ఈ యాప్ను అన్ఇన్స్టాల్ చేయాలనుకుంటున్నారా?"</string>
<string name="uninstall_update_text" msgid="863648314632448705">"ఈ యాప్ను ఫ్యాక్టరీ వెర్షన్తో భర్తీ చేయాలా? మొత్తం డేటా తీసివేయబడుతుంది."</string>
- <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"ఈ యాప్ను ఫ్యాక్టరీ వెర్షన్తో భర్తీ చేయాలా? మొత్తం డేటా తీసివేయబడుతుంది. దీని ప్రభావం కార్యాలయ ప్రొఫైల్లు కలిగి ఉన్నవారితో సహా ఈ పరికర వినియోగదారులందరిపై ఉంటుంది."</string>
+ <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"ఈ యాప్ను ఫ్యాక్టరీ వెర్షన్తో భర్తీ చేయాలా? మొత్తం డేటా తీసివేయబడుతుంది. దీని ప్రభావం కార్యాలయ ప్రొఫైళ్లు కలిగి ఉన్నవారితో సహా ఈ పరికర వినియోగదారులందరిపై ఉంటుంది."</string>
<string name="uninstall_keep_data" msgid="7002379587465487550">"<xliff:g id="SIZE">%1$s</xliff:g> యాప్ డేటాని ఉంచండి."</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"అన్ఇన్స్టాల్ చేయబడుతున్నవి"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"విఫలమైన అన్ఇన్స్టాల్లు"</string>
@@ -69,7 +69,7 @@
<string name="uninstall_failed_app" msgid="5506028705017601412">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> అన్ఇన్స్టాల్ చేయడంలో విఫలమైంది."</string>
<string name="uninstall_failed_device_policy_manager" msgid="785293813665540305">"యాక్టివ్ పరికర నిర్వాహక యాప్ను అన్ఇన్స్టాల్ చేయడం సాధ్యపడదు"</string>
<string name="uninstall_failed_device_policy_manager_of_user" msgid="4813104025494168064">"<xliff:g id="USERNAME">%1$s</xliff:g> కోసం యాక్టివ్ పరికర నిర్వాహక యాప్ను అన్ఇన్స్టాల్ చేయడం సాధ్యపడదు"</string>
- <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"ఈ యాప్ కొందరు వినియోగదారులకు లేదా కొన్ని ప్రొఫైల్లకు అవసరం, ఇతరులకు అన్ఇన్స్టాల్ చేయబడింది"</string>
+ <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"ఈ యాప్ కొందరు వినియోగదారులకు లేదా కొన్ని ప్రొఫైళ్లకు అవసరం, ఇతరులకు అన్ఇన్స్టాల్ చేయబడింది"</string>
<string name="uninstall_blocked_profile_owner" msgid="6373897407002404848">"మీ ప్రొఫైల్ కోసం ఈ యాప్ అవసరం, అందువల్ల దీన్ని అన్ఇన్స్టాల్ చేయడం కుదరదు."</string>
<string name="uninstall_blocked_device_owner" msgid="6724602931761073901">"మీ పరికర నిర్వాహకులకు ఈ యాప్ అవసరం, అందువల్ల దీన్ని అన్ఇన్స్టాల్ చేయడం కుదరదు."</string>
<string name="manage_device_administrators" msgid="3092696419363842816">"పరికర నిర్వాహక యాప్లను నిర్వహించు"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index aab7a5a..1811c26 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -216,7 +216,7 @@
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Empareja nuevos dispositivos con el escáner de códigos QR"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Emparejar dispositivo con código de sincronización"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Empareja nuevos dispositivos con un código de seis dígitos"</string>
- <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos vinculados"</string>
+ <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos emparejados"</string>
<string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectados actualmente"</string>
<string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Datos del dispositivo"</string>
<string name="adb_device_forget" msgid="193072400783068417">"Olvidar"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 4136ec2..efb887a 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -408,7 +408,7 @@
<string name="transcode_notification" msgid="5560515979793436168">"Mostrar notificações de transcodificação"</string>
<string name="transcode_disable_cache" msgid="3160069309377467045">"Desativar cache da transcodificação"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
- <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
+ <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver e controlar os serviços em execução no momento"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Configurar implementação do WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Esta opção não é mais válida. Tente novamente."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 4136ec2..efb887a 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -408,7 +408,7 @@
<string name="transcode_notification" msgid="5560515979793436168">"Mostrar notificações de transcodificação"</string>
<string name="transcode_disable_cache" msgid="3160069309377467045">"Desativar cache da transcodificação"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
- <string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
+ <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver e controlar os serviços em execução no momento"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Configurar implementação do WebView"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Esta opção não é mais válida. Tente novamente."</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index a383c1e..326161b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -164,6 +164,31 @@
return sessionInfos.get(sessionInfos.size() - 1);
}
+ boolean isRoutingSessionAvailableForVolumeControl() {
+ if (mVolumeAdjustmentForRemoteGroupSessions) {
+ return true;
+ }
+ List<RoutingSessionInfo> sessions =
+ mRouterManager.getRoutingSessions(mPackageName);
+ boolean foundNonSystemSession = false;
+ boolean isGroup = false;
+ for (RoutingSessionInfo session : sessions) {
+ if (!session.isSystemSession()) {
+ foundNonSystemSession = true;
+ int selectedRouteCount = session.getSelectedRoutes().size();
+ if (selectedRouteCount > 1) {
+ isGroup = true;
+ break;
+ }
+ }
+ }
+ if (!foundNonSystemSession) {
+ Log.d(TAG, "No routing session for " + mPackageName);
+ return false;
+ }
+ return !isGroup;
+ }
+
/**
* Remove a {@code device} from current media.
*
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index c40b7b7..9092024 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -171,8 +171,8 @@
}
}
- if (device == mCurrentConnectedDevice) {
- Log.d(TAG, "connectDevice() this device all ready connected! : " + device.getName());
+ if (device.equals(mCurrentConnectedDevice)) {
+ Log.d(TAG, "connectDevice() this device is already connected! : " + device.getName());
return false;
}
@@ -196,6 +196,14 @@
}
/**
+ * Returns if the media session is available for volume control.
+ * @return True if this media session is available for colume control, false otherwise.
+ */
+ public boolean isMediaSessionAvailableForVolumeControl() {
+ return mInfoMediaManager.isRoutingSessionAvailableForVolumeControl();
+ }
+
+ /**
* Start scan connected MediaDevice
*/
public void startScan() {
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 510161c..6dc546a 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -710,7 +710,7 @@
<string name="running_foreground_services_title" msgid="5137313173431186685">"Aplikacije koje rade u pozadini"</string>
<string name="running_foreground_services_msg" msgid="3009459259222695385">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string>
<string name="mobile_data_disable_title" msgid="5366476131671617790">"Isključiti prijenos podataka na mobilnoj mreži?"</string>
- <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nećete imati pristup podacima ni internetu putem mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo putem WiFi mreže."</string>
+ <string name="mobile_data_disable_message" msgid="8604966027899770415">"Nećete imati pristup podacima ni internetu putem mobilnog operatera <xliff:g id="CARRIER">%s</xliff:g>. Internet će biti dostupan samo putem WiFi-ja."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"vaš operater"</string>
<string name="touch_filtered_warning" msgid="8119511393338714836">"Postavke ne mogu potvrditi vaš odgovor jer aplikacija zaklanja zahtjev za odobrenje."</string>
<string name="slice_permission_title" msgid="3262615140094151017">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index c4c676f..1c12307 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -49,7 +49,7 @@
<string name="wifi_debugging_title" msgid="7300007687492186076">"اشکالزدایی بیسیم در این شبکه مجاز شود؟"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"نام شبکه (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nنشانی Wi‑Fi (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
<string name="wifi_debugging_always" msgid="2968383799517975155">"همیشه در این شبکه مجاز شود"</string>
- <string name="wifi_debugging_allow" msgid="4573224609684957886">"مجاز بودن"</string>
+ <string name="wifi_debugging_allow" msgid="4573224609684957886">"مجاز است"</string>
<string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"اشکالزدایی بیسیم مجاز نیست"</string>
<string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"کاربری که درحالحاضر در این دستگاه به سیستم وارد شده است نمیتواند اشکالزدایی بیسیم را روشن کند. برای استفاده از این ویژگی، به کاربر اصلی بروید."</string>
<string name="usb_contaminant_title" msgid="894052515034594113">"درگاه USB غیرفعال شده است"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 67518b9..361fa70 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -171,7 +171,7 @@
<skip />
<string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ಅಧಿಸೂಚನೆಯ ಛಾಯೆ."</string>
<string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳು."</string>
- <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ಲಾಕ್ ಪರದೆ."</string>
+ <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ಲಾಕ್ ಸ್ಕ್ರೀನ್."</string>
<string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ಕೆಲಸದ ಲಾಕ್ ಪರದೆ"</string>
<string name="accessibility_desc_close" msgid="8293708213442107755">"ಮುಚ್ಚು"</string>
<string name="accessibility_quick_settings_wifi_changed_off" msgid="2230487165558877262">"ವೈಫೈ ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 32cb8d5..ad0a127 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -37,7 +37,7 @@
<string name="usb_accessory_confirm_prompt" msgid="5728408382798643421">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
<string name="usb_accessory_uri_prompt" msgid="6756649383432542382">"Nenhum apl. instalado funciona com o USB. Saiba mais sobre o acessório em <xliff:g id="URL">%1$s</xliff:g>"</string>
<string name="title_usb_accessory" msgid="1236358027511638648">"Acessório USB"</string>
- <string name="label_view" msgid="6815442985276363364">"Visualizar"</string>
+ <string name="label_view" msgid="6815442985276363364">"Ver"</string>
<string name="always_use_device" msgid="210535878779644679">"Sempre abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> quando <xliff:g id="USB_DEVICE">%2$s</xliff:g> for conectado"</string>
<string name="always_use_accessory" msgid="1977225429341838444">"Sempre abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> quando <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> for conectado"</string>
<string name="usb_debugging_title" msgid="8274884945238642726">"Permitir a depuração USB?"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 32cb8d5..ad0a127 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -37,7 +37,7 @@
<string name="usb_accessory_confirm_prompt" msgid="5728408382798643421">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string>
<string name="usb_accessory_uri_prompt" msgid="6756649383432542382">"Nenhum apl. instalado funciona com o USB. Saiba mais sobre o acessório em <xliff:g id="URL">%1$s</xliff:g>"</string>
<string name="title_usb_accessory" msgid="1236358027511638648">"Acessório USB"</string>
- <string name="label_view" msgid="6815442985276363364">"Visualizar"</string>
+ <string name="label_view" msgid="6815442985276363364">"Ver"</string>
<string name="always_use_device" msgid="210535878779644679">"Sempre abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> quando <xliff:g id="USB_DEVICE">%2$s</xliff:g> for conectado"</string>
<string name="always_use_accessory" msgid="1977225429341838444">"Sempre abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> quando <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> for conectado"</string>
<string name="usb_debugging_title" msgid="8274884945238642726">"Permitir a depuração USB?"</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java
index 543232d..9e59acb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java
@@ -111,6 +111,7 @@
@Override
public void destroy() {
mSource.removeCallback(this);
+ mSource.destroy();
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
index a7840cb..87e853c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
@@ -31,6 +31,8 @@
import android.view.ViewGroup;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.internal.policy.SystemBarUtils;
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -58,6 +60,11 @@
private ColorStateList mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR);
private boolean mBouncerVisible;
private boolean mAltBouncerShowing;
+ /**
+ * Container that wraps the KeyguardMessageArea - may be null if current view hierarchy doesn't
+ * contain {@link R.id.keyguard_message_area_container}.
+ */
+ @Nullable
private ViewGroup mContainer;
private int mContainerTopMargin;
private int mLastOrientation = -1;
@@ -77,6 +84,9 @@
}
void onConfigChanged(Configuration newConfig) {
+ if (mContainer == null) {
+ return;
+ }
final int newTopMargin = SystemBarUtils.getStatusBarHeight(getContext());
if (mContainerTopMargin != newTopMargin) {
mContainerTopMargin = newTopMargin;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2789e27..42f0fcc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1186,6 +1186,21 @@
return fingerprintAllowed || faceAllowed;
}
+ /**
+ * Returns whether the user is unlocked with a biometric that is currently bypassing
+ * the lock screen.
+ */
+ public boolean getUserUnlockedWithBiometricAndIsBypassing(int userId) {
+ BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
+ BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
+ // fingerprint always bypasses
+ boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated
+ && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric);
+ boolean faceAllowed = face != null && face.mAuthenticated
+ && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric);
+ return fingerprintAllowed || faceAllowed && mKeyguardBypassController.canBypass();
+ }
+
public boolean getUserTrustIsManaged(int userId) {
return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index befb648..789ad62 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -118,9 +118,11 @@
switch (this) {
case UNINITIALIZED:
case INITIALIZED:
- case DOZE_REQUEST_PULSE:
return parameters.shouldControlScreenOff() ? Display.STATE_ON
: Display.STATE_OFF;
+ case DOZE_REQUEST_PULSE:
+ return parameters.getDisplayNeedsBlanking() ? Display.STATE_OFF
+ : Display.STATE_ON;
case DOZE_AOD_PAUSED:
case DOZE:
return Display.STATE_OFF;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 3631938..52db1bd 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -105,17 +105,7 @@
updateUdfpsController();
if (mUdfpsController == null) {
- mAuthController.addCallback(new AuthController.Callback() {
- @Override
- public void onAllAuthenticatorsRegistered() {
- updateUdfpsController();
- }
-
- @Override
- public void onEnrollmentsChanged() {
- updateUdfpsController();
- }
- });
+ mAuthController.addCallback(mAuthControllerCallback);
}
}
@@ -128,6 +118,11 @@
}
@Override
+ public void destroy() {
+ mAuthController.removeCallback(mAuthControllerCallback);
+ }
+
+ @Override
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
int screenState = newState.screenState(mParameters);
mDozeHost.cancelGentleSleep();
@@ -222,4 +217,16 @@
mWakeLock.setAcquired(false);
}
}
+
+ private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
+ @Override
+ public void onAllAuthenticatorsRegistered() {
+ updateUdfpsController();
+ }
+
+ @Override
+ public void onEnrollmentsChanged() {
+ updateUdfpsController();
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index c8cd432..a7640ff 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -28,6 +28,7 @@
import android.view.ViewGroup
import android.view.ViewGroupOverlay
import androidx.annotation.VisibleForTesting
+import com.android.keyguard.KeyguardViewController
import com.android.systemui.R
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
@@ -39,7 +40,6 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.Utils
@@ -82,7 +82,7 @@
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
configurationController: ConfigurationController,
wakefulnessLifecycle: WakefulnessLifecycle,
- private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+ private val keyguardViewController: KeyguardViewController
) {
/**
@@ -998,7 +998,7 @@
private fun isLockScreenVisibleToUser(): Boolean {
return !statusBarStateController.isDozing &&
- !statusBarKeyguardViewManager.isBouncerShowing &&
+ !keyguardViewController.isBouncerShowing &&
statusBarStateController.state == StatusBarState.KEYGUARD &&
notifLockscreenUserManager.shouldShowLockscreenNotifications() &&
statusBarStateController.isExpanded &&
@@ -1007,7 +1007,7 @@
private fun isLockScreenShadeVisibleToUser(): Boolean {
return !statusBarStateController.isDozing &&
- !statusBarKeyguardViewManager.isBouncerShowing &&
+ !keyguardViewController.isBouncerShowing &&
(statusBarStateController.state == StatusBarState.SHADE_LOCKED ||
(statusBarStateController.state == StatusBarState.KEYGUARD && qsExpanded))
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 113ba59..e01916f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -177,13 +177,9 @@
mConnectedItem = mContainerLayout;
mBottomDivider.setVisibility(View.GONE);
mCheckBox.setVisibility(View.GONE);
- if (mController.getSelectableMediaDevice().size() > 0) {
- mAddIcon.setVisibility(View.VISIBLE);
- mAddIcon.setTransitionAlpha(1);
- mAddIcon.setOnClickListener(this::onEndItemClick);
- } else {
- mAddIcon.setVisibility(View.GONE);
- }
+ mAddIcon.setVisibility(View.VISIBLE);
+ mAddIcon.setTransitionAlpha(1);
+ mAddIcon.setOnClickListener(this::onEndItemClick);
mTitleIcon.setImageDrawable(getSpeakerDrawable());
final CharSequence sessionName = mController.getSessionName();
final CharSequence title = TextUtils.isEmpty(sessionName)
@@ -198,7 +194,10 @@
if (mController.isTransferring()) {
return;
}
-
+ if (isCurrentlyConnected(device)) {
+ Log.d(TAG, "This device is already connected! : " + device.getName());
+ return;
+ }
mCurrentActivePosition = -1;
playSwitchingAnim(mConnectedItem, view);
mController.connectDevice(device);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index f2cb254..b309c1b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -150,6 +150,10 @@
}
void refresh() {
+ refresh(false);
+ }
+
+ void refresh(boolean deviceSetChanged) {
// Update header icon
final int iconRes = getHeaderIconRes();
final IconCompat iconCompat = getHeaderIcon();
@@ -175,7 +179,8 @@
}
if (!mAdapter.isDragging() && !mAdapter.isAnimating()) {
int currentActivePosition = mAdapter.getCurrentActivePosition();
- if (currentActivePosition >= 0 && currentActivePosition < mAdapter.getItemCount()) {
+ if (!deviceSetChanged && currentActivePosition >= 0
+ && currentActivePosition < mAdapter.getItemCount()) {
mAdapter.notifyItemChanged(currentActivePosition);
} else {
mAdapter.notifyDataSetChanged();
@@ -215,6 +220,11 @@
}
@Override
+ public void onDeviceListChanged() {
+ mMainThreadHandler.post(() -> refresh(true));
+ }
+
+ @Override
public void dismissDialog() {
dismiss();
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index a1e2c57..0d368fa 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -84,7 +84,6 @@
private final SystemUIDialogManager mDialogManager;
private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
private final boolean mAboveStatusbar;
- private final boolean mVolumeAdjustmentForRemoteGroupSessions;
private final NotificationEntryManager mNotificationEntryManager;
@VisibleForTesting
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
@@ -117,8 +116,6 @@
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
mUiEventLogger = uiEventLogger;
mDialogLaunchAnimator = dialogLaunchAnimator;
- mVolumeAdjustmentForRemoteGroupSessions = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions);
mDialogManager = dialogManager;
}
@@ -166,7 +163,7 @@
@Override
public void onDeviceListUpdate(List<MediaDevice> devices) {
buildMediaDevices(devices);
- mCallback.onRouteChanged();
+ mCallback.onDeviceListChanged();
}
@Override
@@ -496,10 +493,15 @@
|| features.contains(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK));
}
+ private boolean isPlayBackInfoLocal() {
+ return mMediaController.getPlaybackInfo() != null
+ && mMediaController.getPlaybackInfo().getPlaybackType()
+ == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL;
+ }
+
boolean isVolumeControlEnabled(@NonNull MediaDevice device) {
- // TODO(b/202500642): Also enable volume control for remote non-group sessions.
- return !isActiveRemoteDevice(device)
- || mVolumeAdjustmentForRemoteGroupSessions;
+ return isPlayBackInfoLocal()
+ || mLocalMediaManager.isMediaSessionAvailableForVolumeControl();
}
private final MediaController.Callback mCb = new MediaController.Callback() {
@@ -529,11 +531,16 @@
void onMediaStoppedOrPaused();
/**
- * Override to handle the device updating.
+ * Override to handle the device status or attributes updating.
*/
void onRouteChanged();
/**
+ * Override to handle the devices set updating.
+ */
+ void onDeviceListChanged();
+
+ /**
* Override to dismiss dialog.
*/
void dismissDialog();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index e82e9d2..e348f2c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -428,7 +428,6 @@
public void setBrightnessMirrorController(
BrightnessMirrorController brightnessMirrorController) {
mQSPanelController.setBrightnessMirror(brightnessMirrorController);
- mQuickQSPanelController.setBrightnessMirror(brightnessMirrorController);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 001c740e..1837b5b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -182,7 +182,9 @@
/** */
public void setListening(boolean listening, boolean expanded) {
- setListening(listening && expanded);
+ // TODO(218268829): checking for split shade is workaround but when proper fix lands
+ // "|| mShouldUseSplitNotificationShade" should be removed
+ setListening(listening && (expanded || mShouldUseSplitNotificationShade));
if (mView.isListening()) {
refreshAllTiles();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
deleted file mode 100644
index 65889d7..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs
-
-import androidx.annotation.VisibleForTesting
-import com.android.systemui.settings.brightness.BrightnessController
-import com.android.systemui.settings.brightness.BrightnessSliderController
-import com.android.systemui.settings.brightness.MirroredBrightnessController
-import com.android.systemui.statusbar.policy.BrightnessMirrorController
-import javax.inject.Inject
-
-/**
- * Controls brightness slider in QQS, which is visible only in split shade. It's responsible for
- * showing/hiding it when appropriate and (un)registering listeners
- */
-class QuickQSBrightnessController @VisibleForTesting constructor(
- private val brightnessControllerFactory: () -> BrightnessController
-) : MirroredBrightnessController {
-
- @Inject constructor(
- brightnessControllerFactory: BrightnessController.Factory,
- brightnessSliderControllerFactory: BrightnessSliderController.Factory,
- quickQSPanel: QuickQSPanel
- ) : this(brightnessControllerFactory = {
- val slider = brightnessSliderControllerFactory.create(quickQSPanel.context,
- quickQSPanel)
- slider.init()
- quickQSPanel.setBrightnessView(slider.rootView)
- brightnessControllerFactory.create(slider)
- })
-
- private var isListening = false
- private var brightnessController: BrightnessController? = null
- private var mirrorController: BrightnessMirrorController? = null
-
- fun init(shouldUseSplitNotificationShade: Boolean) {
- refreshVisibility(shouldUseSplitNotificationShade)
- }
-
- /**
- * Starts/Stops listening for brightness changing events.
- * It's fine to call this function even if slider is not visible (which would be the case for
- * all small screen devices), it will just do nothing in that case
- */
- fun setListening(listening: Boolean) {
- if (listening) {
- // controller can be null when slider was never shown
- if (!isListening && brightnessController != null) {
- brightnessController?.registerCallbacks()
- isListening = true
- }
- } else {
- brightnessController?.unregisterCallbacks()
- isListening = false
- }
- }
-
- fun checkRestrictionAndSetEnabled() {
- brightnessController?.checkRestrictionAndSetEnabled()
- }
-
- fun refreshVisibility(shouldUseSplitNotificationShade: Boolean) {
- if (shouldUseSplitNotificationShade) {
- showBrightnessSlider()
- } else {
- hideBrightnessSlider()
- }
- }
-
- override fun setMirror(controller: BrightnessMirrorController) {
- mirrorController = controller
- mirrorController?.let { brightnessController?.setMirror(it) }
- }
-
- private fun hideBrightnessSlider() {
- brightnessController?.hideSlider()
- }
-
- private fun showBrightnessSlider() {
- if (brightnessController == null) {
- brightnessController = brightnessControllerFactory()
- mirrorController?.also { brightnessController?.setMirror(it) }
- brightnessController?.registerCallbacks()
- isListening = true
- }
- brightnessController?.showSlider()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 92690c7d..fdd764c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -30,8 +30,6 @@
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import java.util.ArrayList;
import java.util.List;
@@ -51,9 +49,6 @@
}
};
- // brightness is visible only in split shade
- private final QuickQSBrightnessController mBrightnessController;
- private final BrightnessMirrorHandler mBrightnessMirrorHandler;
private final FooterActionsController mFooterActionsController;
@Inject
@@ -63,13 +58,10 @@
@Named(QUICK_QS_PANEL) MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager,
- QuickQSBrightnessController quickQSBrightnessController,
@Named(QQS_FOOTER) FooterActionsController footerActionsController
) {
super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
uiEventLogger, qsLogger, dumpManager);
- mBrightnessController = quickQSBrightnessController;
- mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
mFooterActionsController = footerActionsController;
}
@@ -79,7 +71,6 @@
mMediaHost.setExpansion(0.0f);
mMediaHost.setShowsOnlyActiveMedia(true);
mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
- mBrightnessController.init(mShouldUseSplitNotificationShade);
mFooterActionsController.init();
mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade);
}
@@ -88,20 +79,17 @@
protected void onViewAttached() {
super.onViewAttached();
mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
- mBrightnessMirrorHandler.onQsPanelAttached();
}
@Override
protected void onViewDetached() {
super.onViewDetached();
mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
- mBrightnessMirrorHandler.onQsPanelDettached();
}
@Override
void setListening(boolean listening) {
super.setListening(listening);
- mBrightnessController.setListening(listening);
mFooterActionsController.setListening(listening);
}
@@ -115,14 +103,7 @@
}
@Override
- public void refreshAllTiles() {
- mBrightnessController.checkRestrictionAndSetEnabled();
- super.refreshAllTiles();
- }
-
- @Override
protected void onConfigurationChanged() {
- mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade);
mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade);
}
@@ -146,8 +127,4 @@
public int getNumQuickTiles() {
return mView.getNumQuickTiles();
}
-
- public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) {
- mBrightnessMirrorHandler.setController(brightnessMirrorController);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 464b2b6..e0e9280 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -25,6 +25,7 @@
import android.view.View;
import android.view.ViewGroup;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
@@ -42,6 +43,7 @@
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.Assert;
import com.android.wm.shell.bubbles.Bubbles;
@@ -92,6 +94,8 @@
private final KeyguardBypassController mBypassController;
private final ForegroundServiceSectionController mFgsSectionController;
private AssistantFeedbackController mAssistantFeedbackController;
+ private final KeyguardStateController mKeyguardStateController;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final Context mContext;
private NotificationPresenter mPresenter;
@@ -121,7 +125,9 @@
ForegroundServiceSectionController fgsSectionController,
DynamicChildBindController dynamicChildBindController,
LowPriorityInflationHelper lowPriorityInflationHelper,
- AssistantFeedbackController assistantFeedbackController) {
+ AssistantFeedbackController assistantFeedbackController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ KeyguardStateController keyguardStateController) {
mContext = context;
mHandler = mainHandler;
mFeatureFlags = featureFlags;
@@ -140,6 +146,8 @@
mDynamicChildBindController = dynamicChildBindController;
mLowPriorityInflationHelper = lowPriorityInflationHelper;
mAssistantFeedbackController = assistantFeedbackController;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mKeyguardStateController = keyguardStateController;
}
public void setUpWithPresenter(NotificationPresenter presenter,
@@ -163,6 +171,11 @@
beginUpdate();
+ boolean dynamicallyUnlocked = mDynamicPrivacyController.isDynamicallyUnlocked()
+ && !(mStatusBarStateController.getState() == StatusBarState.KEYGUARD
+ && mKeyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(
+ KeyguardUpdateMonitor.getCurrentUser()))
+ && !mKeyguardStateController.isKeyguardGoingAway();
List<NotificationEntry> activeNotifications = mEntryManager.getVisibleNotifications();
ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size());
final int N = activeNotifications.size();
@@ -181,7 +194,7 @@
boolean devicePublic = mLockscreenUserManager.isLockscreenPublicMode(currentUserId);
boolean userPublic = devicePublic
|| mLockscreenUserManager.isLockscreenPublicMode(userId);
- if (userPublic && mDynamicPrivacyController.isDynamicallyUnlocked()
+ if (userPublic && dynamicallyUnlocked
&& (userId == currentUserId || userId == UserHandle.USER_ALL
|| !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) {
userPublic = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index f2d926d..4c5522f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -23,6 +23,7 @@
import android.service.dreams.IDreamManager;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.DialogLaunchAnimator;
import com.android.systemui.dagger.SysUISingleton;
@@ -69,6 +70,7 @@
import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.window.StatusBarWindowController;
import com.android.systemui.tracing.ProtoTracer;
@@ -201,7 +203,9 @@
ForegroundServiceSectionController fgsSectionController,
DynamicChildBindController dynamicChildBindController,
LowPriorityInflationHelper lowPriorityInflationHelper,
- AssistantFeedbackController assistantFeedbackController) {
+ AssistantFeedbackController assistantFeedbackController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ KeyguardStateController keyguardStateController) {
return new NotificationViewHierarchyManager(
context,
mainHandler,
@@ -217,7 +221,9 @@
fgsSectionController,
dynamicChildBindController,
lowPriorityInflationHelper,
- assistantFeedbackController);
+ assistantFeedbackController,
+ keyguardUpdateMonitor,
+ keyguardStateController);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index fe1cd7b..4371091 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -157,6 +157,8 @@
}
}
+ // TODO(b/206118999): merge this class with SensitiveContentCoordinator which also depends on
+ // these same updates
private void setupInvalidateNotifListCallbacks() {
// register onKeyguardShowing callback
mKeyguardStateController.addCallback(mKeyguardCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
index a115e04..9c82cb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
@@ -17,7 +17,10 @@
package com.android.systemui.statusbar.notification.collection.coordinator
import android.os.UserHandle
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.DynamicPrivacyController
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.ListEntry
@@ -26,6 +29,7 @@
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
+import com.android.systemui.statusbar.policy.KeyguardStateController
import dagger.Module
import dagger.Provides
@@ -36,9 +40,13 @@
@CoordinatorScope
fun provideCoordinator(
dynamicPrivacyController: DynamicPrivacyController,
- lockscreenUserManager: NotificationLockscreenUserManager
+ lockscreenUserManager: NotificationLockscreenUserManager,
+ keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ statusBarStateController: StatusBarStateController,
+ keyguardStateController: KeyguardStateController
): SensitiveContentCoordinator =
- SensitiveContentCoordinatorImpl(dynamicPrivacyController, lockscreenUserManager)
+ SensitiveContentCoordinatorImpl(dynamicPrivacyController, lockscreenUserManager,
+ keyguardUpdateMonitor, statusBarStateController, keyguardStateController)
}
/** Coordinates re-inflation and post-processing of sensitive notification content. */
@@ -46,7 +54,10 @@
private class SensitiveContentCoordinatorImpl(
private val dynamicPrivacyController: DynamicPrivacyController,
- private val lockscreenUserManager: NotificationLockscreenUserManager
+ private val lockscreenUserManager: NotificationLockscreenUserManager,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ private val statusBarStateController: StatusBarStateController,
+ private val keyguardStateController: KeyguardStateController
) : Invalidator("SensitiveContentInvalidator"),
SensitiveContentCoordinator,
DynamicPrivacyController.Listener,
@@ -61,6 +72,19 @@
override fun onDynamicPrivacyChanged(): Unit = invalidateList()
override fun onBeforeRenderList(entries: List<ListEntry>) {
+ if (keyguardStateController.isKeyguardGoingAway() ||
+ statusBarStateController.getState() == StatusBarState.KEYGUARD &&
+ keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(
+ KeyguardUpdateMonitor.getCurrentUser())) {
+ // don't update yet if:
+ // - the keyguard is currently going away
+ // - LS is about to be dismissed by a biometric that bypasses LS (avoid notif flash)
+
+ // TODO(b/206118999): merge this class with KeyguardCoordinator which ensures the
+ // dependent state changes invalidate the pipeline
+ return
+ }
+
val currentUserId = lockscreenUserManager.currentUserId
val devicePublic = lockscreenUserManager.isLockscreenPublicMode(currentUserId)
val deviceSensitive = devicePublic &&
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index f14cc93c..9f44060 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -279,11 +279,11 @@
@Override
public void onThemeChanged() {
- updateShowEmptyShadeView();
mView.updateCornerRadius();
mView.updateBgColor();
mView.updateDecorViews();
mView.reinflateViews();
+ updateShowEmptyShadeView();
updateFooter();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 2c70a5f..c4567df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -376,6 +376,11 @@
final float stackHeight = ambientState.getStackHeight() - shelfHeight - scrimPadding;
final float stackEndHeight = ambientState.getStackEndHeight() - shelfHeight - scrimPadding;
+ if (stackEndHeight == 0f) {
+ // This should not happen, since even when the shade is empty we show EmptyShadeView
+ // but check just in case, so we don't return infinity or NaN.
+ return 0f;
+ }
return stackHeight / stackEndHeight;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 8078b6c..5684429 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -42,12 +42,14 @@
import android.hardware.display.AmbientDisplayConfiguration;
import android.testing.AndroidTestingRunner;
import android.testing.UiThreadTest;
+import android.view.Display;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.wakelock.WakeLockFake;
@@ -444,4 +446,20 @@
assertTrue(mServiceFake.requestedWakeup);
}
+
+ @Test
+ public void testDozePulsing_displayRequiresBlanking_screenState() {
+ DozeParameters dozeParameters = mock(DozeParameters.class);
+ when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
+
+ assertEquals(Display.STATE_OFF, DOZE_REQUEST_PULSE.screenState(dozeParameters));
+ }
+
+ @Test
+ public void testDozePulsing_displayDoesNotRequireBlanking_screenState() {
+ DozeParameters dozeParameters = mock(DozeParameters.class);
+ when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(false);
+
+ assertEquals(Display.STATE_ON, DOZE_REQUEST_PULSE.screenState(dozeParameters));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 3e19cc4..992a82b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -35,6 +35,7 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
@@ -306,4 +307,11 @@
// THEN the display screen state will change
assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
}
+
+ @Test
+ public void authCallbackRemovedOnDestroy() {
+ mScreen.destroy();
+
+ verify(mAuthController).removeCallback(anyObject());
+ }
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
index a3ffb2f..7565fe1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
@@ -22,6 +22,7 @@
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardViewController
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
@@ -31,7 +32,6 @@
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.phone.KeyguardBypassController
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.animation.UniqueObjectHostView
@@ -80,7 +80,7 @@
@Mock
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock
- private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+ private lateinit var keyguardViewController: KeyguardViewController
@Mock
private lateinit var configurationController: ConfigurationController
@Mock
@@ -110,7 +110,7 @@
notificationLockscreenUserManager,
configurationController,
wakefulnessLifecycle,
- statusBarKeyguardViewManager)
+ keyguardViewController)
verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
verify(statusBarStateController).addCallback(statusBarCallback.capture())
setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index cd26e0d..b5c501a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -201,7 +201,7 @@
assertThat(devices.containsAll(mMediaDevices)).isTrue();
assertThat(devices.size()).isEqualTo(mMediaDevices.size());
- verify(mCb).onRouteChanged();
+ verify(mCb).onDeviceListChanged();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt
deleted file mode 100644
index de1d86b..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.settings.brightness.BrightnessController
-import com.android.systemui.statusbar.policy.BrightnessMirrorController
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.mockito.Mock
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.never
-import org.mockito.Mockito.mock
-import org.mockito.junit.MockitoJUnit
-
-@SmallTest
-class QuickQSBrightnessControllerTest : SysuiTestCase() {
-
- @Mock
- lateinit var brightnessController: BrightnessController
- @get:Rule
- val mockito = MockitoJUnit.rule()
-
- lateinit var quickQSBrightnessController: QuickQSBrightnessController
-
- @Before
- fun setUp() {
- quickQSBrightnessController = QuickQSBrightnessController(
- brightnessControllerFactory = { brightnessController })
- }
-
- @Test
- fun testSliderIsShownWhenInitializedInSplitShade() {
- quickQSBrightnessController.init(shouldUseSplitNotificationShade = true)
-
- verify(brightnessController).showSlider()
- }
-
- @Test
- fun testSliderIsShownWhenRefreshedInSplitShade() {
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-
- verify(brightnessController, times(1)).showSlider()
- }
-
- @Test
- fun testSliderIsHiddenWhenRefreshedInNonSplitShade() {
- // needs to be shown first
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
-
- verify(brightnessController).hideSlider()
- }
-
- @Test
- fun testSliderChangesVisibilityWhenRotating() {
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
- verify(brightnessController, times(1)).showSlider()
-
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
- verify(brightnessController, times(1)).hideSlider()
- }
-
- @Test
- fun testCallbacksAreRegisteredOnlyOnce() {
- // this flow simulates expanding shade in portrait...
- quickQSBrightnessController.setListening(true)
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
- // ... and rotating to landscape/split shade where slider is visible
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-
- verify(brightnessController, times(1)).registerCallbacks()
- }
-
- @Test
- fun testCallbacksAreRegisteredOnlyOnceWhenRotatingPhone() {
- quickQSBrightnessController.setListening(true)
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-
- verify(brightnessController, times(1)).registerCallbacks()
- }
-
- @Test
- fun testCallbacksAreNotRegisteredWhenSliderNotVisible() {
- quickQSBrightnessController.setListening(true)
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false)
-
- verify(brightnessController, never()).registerCallbacks()
- }
-
- @Test
- fun testMirrorIsSetWhenSliderIsShown() {
- val mirrorController = mock(BrightnessMirrorController::class.java)
- quickQSBrightnessController.setMirror(mirrorController)
- quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true)
-
- verify(brightnessController).setMirror(mirrorController)
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 59948d3..fb8a6e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -67,8 +67,6 @@
@Mock
private lateinit var tileView: QSTileView
@Mock
- private lateinit var quickQsBrightnessController: QuickQSBrightnessController
- @Mock
private lateinit var footerActionsController: FooterActionsController
@Captor
private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener>
@@ -95,7 +93,6 @@
uiEventLogger,
qsLogger,
dumpManager,
- quickQsBrightnessController,
footerActionsController
)
@@ -128,13 +125,11 @@
}
@Test
- fun testBrightnessAndFooterVisibilityRefreshedWhenConfigurationChanged() {
+ fun testFooterVisibilityRefreshedWhenConfigurationChanged() {
// times(2) because both controller and base controller are registering their listeners
verify(quickQSPanel, times(2)).addOnConfigurationChangedListener(captor.capture())
captor.allValues.forEach { it.onConfigurationChange(Configuration.EMPTY) }
-
- verify(quickQsBrightnessController).refreshVisibility(anyBoolean())
// times(2) because footer visibility is also refreshed on controller init
verify(footerActionsController, times(2)).refreshVisibility(anyBoolean())
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index cf58c63..a3e0107 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -35,6 +35,7 @@
import androidx.test.filters.SmallTest;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
@@ -54,6 +55,7 @@
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.wm.shell.bubbles.Bubbles;
import com.google.android.collect.Lists;
@@ -118,7 +120,9 @@
mock(ForegroundServiceSectionController.class),
mock(DynamicChildBindController.class),
mock(LowPriorityInflationHelper.class),
- mock(AssistantFeedbackController.class));
+ mock(AssistantFeedbackController.class),
+ mock(KeyguardUpdateMonitor.class),
+ mock(KeyguardStateController.class));
mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
index 5fd4174..3f84c16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
@@ -19,8 +19,11 @@
import android.os.UserHandle
import android.service.notification.StatusBarNotification
import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.DynamicPrivacyController
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
@@ -28,9 +31,12 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
+import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.withArgCaptor
+import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import org.junit.Test
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
@@ -40,9 +46,13 @@
val dynamicPrivacyController: DynamicPrivacyController = mock()
val lockscreenUserManager: NotificationLockscreenUserManager = mock()
val pipeline: NotifPipeline = mock()
+ val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock()
+ val statusBarStateController: StatusBarStateController = mock()
+ val keyguardStateController: KeyguardStateController = mock()
val coordinator: SensitiveContentCoordinator = SensitiveContentCoordinatorModule
- .provideCoordinator(dynamicPrivacyController, lockscreenUserManager)
+ .provideCoordinator(dynamicPrivacyController, lockscreenUserManager,
+ keyguardUpdateMonitor, statusBarStateController, keyguardStateController)
@Test
fun onDynamicPrivacyChanged_invokeInvalidationListener() {
@@ -190,6 +200,28 @@
verify(entry.representativeEntry!!).setSensitive(true, true)
}
+ @Test
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_deviceBiometricBypassingLockScreen() {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
+ whenever(statusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD)
+ whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(any()))
+ .thenReturn(true)
+
+ val entry = fakeNotification(2, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!, never()).setSensitive(any(), any())
+ }
+
private fun fakeNotification(notifUserId: Int, needsRedaction: Boolean): ListEntry {
val mockUserHandle = mock<UserHandle>().apply {
whenever(identifier).thenReturn(notifUserId)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 15a92dc..ecfa1aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -1275,6 +1275,22 @@
assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
}
+ @Test
+ public void testStackViewOnBackPressed_updatesBubbleDataExpandState() {
+ mBubbleController.updateBubble(mBubbleEntry);
+
+ // Expand the stack
+ mBubbleData.setExpanded(true);
+ assertStackExpanded();
+
+ // Hit back
+ BubbleStackView stackView = mBubbleController.getStackView();
+ stackView.onBackPressed();
+
+ // Make sure we're collapsed
+ assertStackCollapsed();
+ }
+
/** Creates a bubble using the userId and package. */
private Bubble createBubble(int userId, String pkg) {
final UserHandle userHandle = new UserHandle(userId);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
index 43b181e..6207b76 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
@@ -1091,6 +1091,22 @@
assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
}
+ @Test
+ public void testStackViewOnBackPressed_updatesBubbleDataExpandState() {
+ mBubbleController.updateBubble(mBubbleEntry);
+
+ // Expand the stack
+ mBubbleData.setExpanded(true);
+ assertStackExpanded();
+
+ // Hit back
+ BubbleStackView stackView = mBubbleController.getStackView();
+ stackView.onBackPressed();
+
+ // Make sure we're collapsed
+ assertStackCollapsed();
+ }
+
/**
* Sets the bubble metadata flags for this entry. These flags are normally set by
* NotificationManagerService when the notification is sent, however, these tests do not
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index b068f86..ce74f1f 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -567,7 +567,13 @@
@GuardedBy("mLock")
private void notifyAllPolicyListenersLocked() {
for (final PolicyListenerBinderDeath policyListener : mRegisteredPolicyListeners.values()) {
- Binder.withCleanCallingIdentity(() -> policyListener.mListener.onPolicyChanged());
+ Binder.withCleanCallingIdentity(() -> {
+ try {
+ policyListener.mListener.onPolicyChanged();
+ } catch (RemoteException e) {
+ logDbg("VcnStatusCallback threw on VCN status change", e);
+ }
+ });
}
}
@@ -576,8 +582,13 @@
@NonNull ParcelUuid subGroup, @VcnStatusCode int statusCode) {
for (final VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
if (isCallbackPermissioned(cbInfo, subGroup)) {
- Binder.withCleanCallingIdentity(
- () -> cbInfo.mCallback.onVcnStatusChanged(statusCode));
+ Binder.withCleanCallingIdentity(() -> {
+ try {
+ cbInfo.mCallback.onVcnStatusChanged(statusCode);
+ } catch (RemoteException e) {
+ logDbg("VcnStatusCallback threw on VCN status change", e);
+ }
+ });
}
}
}
@@ -1250,13 +1261,17 @@
// Notify all registered StatusCallbacks for this subGroup
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
if (isCallbackPermissioned(cbInfo, mSubGroup)) {
- Binder.withCleanCallingIdentity(
- () ->
- cbInfo.mCallback.onGatewayConnectionError(
- gatewayConnectionName,
- errorCode,
- exceptionClass,
- exceptionMessage));
+ Binder.withCleanCallingIdentity(() -> {
+ try {
+ cbInfo.mCallback.onGatewayConnectionError(
+ gatewayConnectionName,
+ errorCode,
+ exceptionClass,
+ exceptionMessage);
+ } catch (RemoteException e) {
+ logDbg("VcnStatusCallback threw on VCN status change", e);
+ }
+ });
}
}
}
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index 1f35b88..d91537c 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -18,6 +18,7 @@
import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
+import android.annotation.NonNull;
import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.Notification;
@@ -170,6 +171,12 @@
mAdbConnectionInfo = new AdbConnectionInfo();
}
+ static void sendBroadcastWithDebugPermission(@NonNull Context context, @NonNull Intent intent,
+ @NonNull UserHandle userHandle) {
+ context.sendBroadcastAsUser(intent, userHandle,
+ android.Manifest.permission.MANAGE_DEBUGGING);
+ }
+
class PairingThread extends Thread implements NsdManager.RegistrationListener {
private NsdManager mNsdManager;
private String mPublicKey;
@@ -1278,7 +1285,7 @@
? AdbManager.WIRELESS_STATUS_CONNECTED
: AdbManager.WIRELESS_STATUS_DISCONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void onAdbdWifiServerConnected(int port) {
@@ -1350,7 +1357,8 @@
if (publicKey == null) {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_FAIL);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
+ UserHandle.ALL);
} else {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
@@ -1363,7 +1371,8 @@
}
PairDevice device = new PairDevice(fingerprints, hostname, false);
intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
+ UserHandle.ALL);
// Add the key into the keystore
mAdbKeyStore.setLastConnectionTime(publicKey,
System.currentTimeMillis());
@@ -1377,14 +1386,14 @@
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
AdbManager.WIRELESS_STATUS_CONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void sendPairedDevicesToUI(Map<String, PairDevice> devices) {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
// Map is not serializable, so need to downcast
intent.putExtra(AdbManager.WIRELESS_DEVICES_EXTRA, (HashMap) devices);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void updateUIPairCode(String code) {
@@ -1394,7 +1403,7 @@
intent.putExtra(AdbManager.WIRELESS_PAIRING_CODE_EXTRA, code);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
AdbManager.WIRELESS_STATUS_PAIRING_CODE);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
}
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 29bb542..5b16daa 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -431,7 +431,7 @@
? AdbManager.WIRELESS_STATUS_CONNECTED
: AdbManager.WIRELESS_STATUS_DISCONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
Slog.i(TAG, "sent port broadcast port=" + port);
}
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 2c2a2bf..17215e5 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -131,6 +131,7 @@
private static final int MSG_STOP_SENSOR_LISTENER = 2;
private static final int MSG_START_SENSOR_LISTENER = 3;
private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;
+ private static final int MSG_SENSOR_CHANGED = 5;
private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -158,6 +159,7 @@
// These members should only be accessed on the mBgHandler thread.
private BroadcastReceiver mBroadcastReceiver;
private SensorListener mSensorListener;
+ private Sensor mLightSensor;
private SettingsObserver mSettingsObserver;
private DisplayListener mDisplayListener;
private boolean mSensorRegistered;
@@ -327,6 +329,14 @@
m.sendToTarget();
}
+ /**
+ * Updates the light sensor to use.
+ */
+ public void setLightSensor(Sensor lightSensor) {
+ mBgHandler.obtainMessage(MSG_SENSOR_CHANGED, 0 /*unused*/, 0/*unused*/, lightSensor)
+ .sendToTarget();
+ }
+
private void handleBrightnessChanged(float brightness, boolean userInitiated,
float powerBrightnessFactor, boolean isUserSetBrightness,
boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId) {
@@ -428,13 +438,28 @@
}
}
+ private void handleSensorChanged(Sensor lightSensor) {
+ if (mLightSensor != lightSensor) {
+ mLightSensor = lightSensor;
+ stopSensorListener();
+ synchronized (mDataCollectionLock) {
+ mLastSensorReadings.clear();
+ }
+ // Attempt to restart the sensor listener. It will check to see if it should be running
+ // so there is no need to also check here.
+ startSensorListener();
+ }
+ }
+
private void startSensorListener() {
if (!mSensorRegistered
+ && mLightSensor != null
+ && mAmbientBrightnessStatsTracker != null
&& mInjector.isInteractive(mContext)
&& mInjector.isBrightnessModeAutomatic(mContentResolver)) {
mAmbientBrightnessStatsTracker.start();
mSensorRegistered = true;
- mInjector.registerSensorListener(mContext, mSensorListener,
+ mInjector.registerSensorListener(mContext, mSensorListener, mLightSensor,
mInjector.getBackgroundHandler());
}
}
@@ -736,6 +761,7 @@
pw.println("BrightnessTracker state:");
synchronized (mDataCollectionLock) {
pw.println(" mStarted=" + mStarted);
+ pw.println(" mLightSensor=" + mLightSensor);
pw.println(" mLastBatteryLevel=" + mLastBatteryLevel);
pw.println(" mLastBrightness=" + mLastBrightness);
pw.println(" mLastSensorReadings.size=" + mLastSensorReadings.size());
@@ -1017,6 +1043,9 @@
disableColorSampling();
}
break;
+ case MSG_SENSOR_CHANGED:
+ handleSensorChanged((Sensor) msg.obj);
+ break;
}
}
@@ -1045,9 +1074,8 @@
@VisibleForTesting
static class Injector {
public void registerSensorListener(Context context,
- SensorEventListener sensorListener, Handler handler) {
+ SensorEventListener sensorListener, Sensor lightSensor, Handler handler) {
SensorManager sensorManager = context.getSystemService(SensorManager.class);
- Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
sensorManager.registerListener(sensorListener,
lightSensor, SensorManager.SENSOR_DELAY_NORMAL, handler);
}
diff --git a/services/core/java/com/android/server/display/BrightnessUtils.java b/services/core/java/com/android/server/display/BrightnessUtils.java
new file mode 100644
index 0000000..84fa0cc
--- /dev/null
+++ b/services/core/java/com/android/server/display/BrightnessUtils.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.util.MathUtils;
+
+/**
+ * Utility class providing functions to convert between linear and perceptual gamma space.
+ *
+ * Internally, this implements the Hybrid Log Gamma electro-optical transfer function, which is a
+ * slight improvement to the typical gamma transfer function for displays whose max brightness
+ * exceeds the 120 nit reference point, but doesn't set a specific reference brightness like the PQ
+ * function does.
+ *
+ * Note that this transfer function is only valid if the display's backlight value is a linear
+ * control. If it's calibrated to be something non-linear, then a different transfer function
+ * should be used.
+ *
+ * Note: This code is based on the same class in the com.android.settingslib.display package.
+ */
+public class BrightnessUtils {
+
+ // Hybrid Log Gamma constant values
+ private static final float R = 0.5f;
+ private static final float A = 0.17883277f;
+ private static final float B = 0.28466892f;
+ private static final float C = 0.55991073f;
+
+ /**
+ * A function for converting from the gamma space into the linear space.
+ *
+ * @param val The value in the gamma space [0 .. 1.0]
+ * @return The corresponding value in the linear space [0 .. 1.0].
+ */
+ public static final float convertGammaToLinear(float val) {
+ final float ret;
+ if (val <= R) {
+ ret = MathUtils.sq(val / R);
+ } else {
+ ret = MathUtils.exp((val - C) / A) + B;
+ }
+
+ // HLG is normalized to the range [0, 12], ensure that value is within that range,
+ // it shouldn't be out of bounds.
+ final float normalizedRet = MathUtils.constrain(ret, 0, 12);
+
+ // Re-normalize to the range [0, 1]
+ // in order to derive the correct setting value.
+ return normalizedRet / 12;
+ }
+
+ /**
+ * A function for converting from the linear space into the gamma space.
+ *
+ * @param val The value in linear space [0 .. 1.0]
+ * @return The corresponding value in gamma space [0 .. 1.0]
+ */
+ public static final float convertLinearToGamma(float val) {
+ // For some reason, HLG normalizes to the range [0, 12] rather than [0, 1]
+ final float normalizedVal = val * 12;
+ final float ret;
+ if (normalizedVal <= 1f) {
+ ret = MathUtils.sqrt(normalizedVal) * R;
+ } else {
+ ret = A * MathUtils.log(normalizedVal - B) + C;
+ }
+ return ret;
+ }
+}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 2ae5cbb..255494f9 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -31,6 +31,7 @@
import com.android.internal.R;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.server.display.config.BrightnessThresholds;
import com.android.server.display.config.DisplayConfiguration;
import com.android.server.display.config.DisplayQuirks;
import com.android.server.display.config.HbmTiming;
@@ -40,6 +41,7 @@
import com.android.server.display.config.RefreshRateRange;
import com.android.server.display.config.SensorDetails;
import com.android.server.display.config.ThermalStatus;
+import com.android.server.display.config.Thresholds;
import com.android.server.display.config.XmlParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -115,6 +117,10 @@
private float mBrightnessRampFastIncrease = Float.NaN;
private float mBrightnessRampSlowDecrease = Float.NaN;
private float mBrightnessRampSlowIncrease = Float.NaN;
+ private float mScreenBrighteningMinThreshold = 0.0f; // Retain behaviour as though there is
+ private float mScreenDarkeningMinThreshold = 0.0f; // no minimum threshold for change in
+ private float mAmbientLuxBrighteningMinThreshold = 0.0f; // screen brightness or ambient
+ private float mAmbientLuxDarkeningMinThreshold = 0.0f; // brightness.
private Spline mBrightnessToBacklightSpline;
private Spline mBacklightToBrightnessSpline;
private Spline mBacklightToNitsSpline;
@@ -282,6 +288,22 @@
return mBrightnessRampSlowIncrease;
}
+ public float getScreenBrighteningMinThreshold() {
+ return mScreenBrighteningMinThreshold;
+ }
+
+ public float getScreenDarkeningMinThreshold() {
+ return mScreenDarkeningMinThreshold;
+ }
+
+ public float getAmbientLuxBrighteningMinThreshold() {
+ return mAmbientLuxBrighteningMinThreshold;
+ }
+
+ public float getAmbientLuxDarkeningMinThreshold() {
+ return mAmbientLuxDarkeningMinThreshold;
+ }
+
SensorData getAmbientLightSensor() {
return mAmbientLightSensor;
}
@@ -337,6 +359,10 @@
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
+ ", mBrightnessRampSlowIncrease=" + mBrightnessRampSlowIncrease
+ + ", mScreenDarkeningMinThreshold=" + mScreenDarkeningMinThreshold
+ + ", mScreenBrighteningMinThreshold=" + mScreenBrighteningMinThreshold
+ + ", mAmbientLuxDarkeningMinThreshold=" + mAmbientLuxDarkeningMinThreshold
+ + ", mAmbientLuxBrighteningMinThreshold=" + mAmbientLuxBrighteningMinThreshold
+ ", mAmbientLightSensor=" + mAmbientLightSensor
+ ", mProximitySensor=" + mProximitySensor
+ ", mRefreshRateLimitations= " + Arrays.toString(mRefreshRateLimitations.toArray())
@@ -392,6 +418,7 @@
loadBrightnessRamps(config);
loadAmbientLightSensorFromDdc(config);
loadProxSensorFromDdc(config);
+ loadBrightnessChangeThresholds(config);
} else {
Slog.w(TAG, "DisplayDeviceConfig file is null");
}
@@ -746,6 +773,45 @@
}
}
+ private void loadBrightnessChangeThresholds(DisplayConfiguration config) {
+ Thresholds displayBrightnessThresholds = config.getDisplayBrightnessChangeThresholds();
+ Thresholds ambientBrightnessThresholds = config.getAmbientBrightnessChangeThresholds();
+
+ if (displayBrightnessThresholds != null) {
+ BrightnessThresholds brighteningScreen =
+ displayBrightnessThresholds.getBrighteningThresholds();
+ BrightnessThresholds darkeningScreen =
+ displayBrightnessThresholds.getDarkeningThresholds();
+
+ final BigDecimal screenBrighteningThreshold = brighteningScreen.getMinimum();
+ final BigDecimal screenDarkeningThreshold = darkeningScreen.getMinimum();
+
+ if (screenBrighteningThreshold != null) {
+ mScreenBrighteningMinThreshold = screenBrighteningThreshold.floatValue();
+ }
+ if (screenDarkeningThreshold != null) {
+ mScreenDarkeningMinThreshold = screenDarkeningThreshold.floatValue();
+ }
+ }
+
+ if (ambientBrightnessThresholds != null) {
+ BrightnessThresholds brighteningAmbientLux =
+ ambientBrightnessThresholds.getBrighteningThresholds();
+ BrightnessThresholds darkeningAmbientLux =
+ ambientBrightnessThresholds.getDarkeningThresholds();
+
+ final BigDecimal ambientBrighteningThreshold = brighteningAmbientLux.getMinimum();
+ final BigDecimal ambientDarkeningThreshold = darkeningAmbientLux.getMinimum();
+
+ if (ambientBrighteningThreshold != null) {
+ mAmbientLuxBrighteningMinThreshold = ambientBrighteningThreshold.floatValue();
+ }
+ if (ambientDarkeningThreshold != null) {
+ mAmbientLuxDarkeningMinThreshold = ambientDarkeningThreshold.floatValue();
+ }
+ }
+ }
+
private @PowerManager.ThermalStatus int convertThermalStatus(ThermalStatus value) {
if (value == null) {
return PowerManager.THERMAL_STATUS_NONE;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 22dd2c0..77c1fc0 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -795,7 +795,6 @@
private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) {
// All properties that depend on the associated DisplayDevice and the DDC must be
// updated here.
- loadAmbientLightSensor();
loadBrightnessRampRates();
loadProximitySensor();
loadNitsRange(mContext.getResources());
@@ -880,9 +879,14 @@
com.android.internal.R.array.config_ambientDarkeningThresholds);
int[] ambientThresholdLevels = resources.getIntArray(
com.android.internal.R.array.config_ambientThresholdLevels);
+ float ambientDarkeningMinThreshold =
+ mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold();
+ float ambientBrighteningMinThreshold =
+ mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold();
HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
ambientBrighteningThresholds, ambientDarkeningThresholds,
- ambientThresholdLevels);
+ ambientThresholdLevels, ambientDarkeningMinThreshold,
+ ambientBrighteningMinThreshold);
int[] screenBrighteningThresholds = resources.getIntArray(
com.android.internal.R.array.config_screenBrighteningThresholds);
@@ -890,8 +894,13 @@
com.android.internal.R.array.config_screenDarkeningThresholds);
int[] screenThresholdLevels = resources.getIntArray(
com.android.internal.R.array.config_screenThresholdLevels);
+ float screenDarkeningMinThreshold =
+ mDisplayDeviceConfig.getScreenDarkeningMinThreshold();
+ float screenBrighteningMinThreshold =
+ mDisplayDeviceConfig.getScreenBrighteningMinThreshold();
HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
- screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels);
+ screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels,
+ screenDarkeningMinThreshold, screenBrighteningMinThreshold);
long brighteningLightDebounce = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
@@ -915,6 +924,9 @@
}
loadAmbientLightSensor();
+ if (mBrightnessTracker != null) {
+ mBrightnessTracker.setLightSensor(mLightSensor);
+ }
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.stop();
diff --git a/services/core/java/com/android/server/display/HysteresisLevels.java b/services/core/java/com/android/server/display/HysteresisLevels.java
index 2b56569..7a932ce 100644
--- a/services/core/java/com/android/server/display/HysteresisLevels.java
+++ b/services/core/java/com/android/server/display/HysteresisLevels.java
@@ -30,17 +30,13 @@
public class HysteresisLevels {
private static final String TAG = "HysteresisLevels";
- // Default hysteresis constraints for brightening or darkening.
- // The recent value must have changed by at least this fraction relative to the
- // current value before a change will be considered.
- private static final float DEFAULT_BRIGHTENING_HYSTERESIS = 0.10f;
- private static final float DEFAULT_DARKENING_HYSTERESIS = 0.20f;
-
private static final boolean DEBUG = false;
private final float[] mBrighteningThresholds;
private final float[] mDarkeningThresholds;
private final float[] mThresholdLevels;
+ private final float mMinDarkening;
+ private final float mMinBrightening;
/**
* Creates a {@code HysteresisLevels} object with the given equal-length
@@ -48,9 +44,12 @@
* @param brighteningThresholds an array of brightening hysteresis constraint constants.
* @param darkeningThresholds an array of darkening hysteresis constraint constants.
* @param thresholdLevels a monotonically increasing array of threshold levels.
+ * @param minBrighteningThreshold the minimum value for which the brightening value needs to
+ * return.
+ * @param minDarkeningThreshold the minimum value for which the darkening value needs to return.
*/
HysteresisLevels(int[] brighteningThresholds, int[] darkeningThresholds,
- int[] thresholdLevels) {
+ int[] thresholdLevels, float minDarkeningThreshold, float minBrighteningThreshold) {
if (brighteningThresholds.length != darkeningThresholds.length
|| darkeningThresholds.length != thresholdLevels.length + 1) {
throw new IllegalArgumentException("Mismatch between hysteresis array lengths.");
@@ -58,6 +57,8 @@
mBrighteningThresholds = setArrayFormat(brighteningThresholds, 1000.0f);
mDarkeningThresholds = setArrayFormat(darkeningThresholds, 1000.0f);
mThresholdLevels = setArrayFormat(thresholdLevels, 1.0f);
+ mMinDarkening = minDarkeningThreshold;
+ mMinBrightening = minBrighteningThreshold;
}
/**
@@ -65,11 +66,13 @@
*/
public float getBrighteningThreshold(float value) {
final float brightConstant = getReferenceLevel(value, mBrighteningThresholds);
- final float brightThreshold = value * (1.0f + brightConstant);
+ float brightThreshold = value * (1.0f + brightConstant);
if (DEBUG) {
Slog.d(TAG, "bright hysteresis constant=" + brightConstant + ", threshold="
+ brightThreshold + ", value=" + value);
}
+
+ brightThreshold = Math.max(brightThreshold, value + mMinBrightening);
return brightThreshold;
}
@@ -78,12 +81,13 @@
*/
public float getDarkeningThreshold(float value) {
final float darkConstant = getReferenceLevel(value, mDarkeningThresholds);
- final float darkThreshold = value * (1.0f - darkConstant);
+ float darkThreshold = value * (1.0f - darkConstant);
if (DEBUG) {
Slog.d(TAG, "dark hysteresis constant=: " + darkConstant + ", threshold="
+ darkThreshold + ", value=" + value);
}
- return darkThreshold;
+ darkThreshold = Math.min(darkThreshold, value - mMinDarkening);
+ return Math.max(darkThreshold, 0.0f);
}
/**
diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java
index ed3b15f..d8672fc 100644
--- a/services/core/java/com/android/server/display/RampAnimator.java
+++ b/services/core/java/com/android/server/display/RampAnimator.java
@@ -23,6 +23,8 @@
/**
* A custom animator that progressively updates a property value at
* a given variable rate until it reaches a particular target value.
+ * The ramping at the given rate is done in the perceptual space using
+ * the HLG transfer functions.
*/
class RampAnimator<T> {
private final T mObject;
@@ -57,7 +59,9 @@
* @param rate The convergence rate in units per second, or 0 to set the value immediately.
* @return True if the target differs from the previous target.
*/
- public boolean animateTo(float target, float rate) {
+ public boolean animateTo(float targetLinear, float rate) {
+ // Convert the target from the linear into the HLG space.
+ final float target = BrightnessUtils.convertLinearToGamma(targetLinear);
// Immediately jump to the target the first time.
if (mFirstTime || rate <= 0) {
@@ -66,7 +70,7 @@
mRate = 0;
mTargetValue = target;
mCurrentValue = target;
- mProperty.setValue(mObject, target);
+ setPropertyValue(target);
if (mAnimating) {
mAnimating = false;
cancelAnimationCallback();
@@ -121,6 +125,15 @@
mListener = listener;
}
+ /**
+ * Sets the brightness property by converting the given value from HLG space
+ * into linear space.
+ */
+ private void setPropertyValue(float val) {
+ final float linearVal = BrightnessUtils.convertGammaToLinear(val);
+ mProperty.setValue(mObject, linearVal);
+ }
+
private void postAnimationCallback() {
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
}
@@ -156,7 +169,7 @@
final float oldCurrentValue = mCurrentValue;
mCurrentValue = mAnimatedValue;
if (oldCurrentValue != mCurrentValue) {
- mProperty.setValue(mObject, mCurrentValue);
+ setPropertyValue(mCurrentValue);
}
if (mTargetValue != mCurrentValue) {
postAnimationCallback();
@@ -201,14 +214,14 @@
* If this is the first time the property is being set or if the rate is 0,
* the value jumps directly to the target.
*
- * @param firstTarget The first target value.
- * @param secondTarget The second target value.
+ * @param linearFirstTarget The first target value in linear space.
+ * @param linearSecondTarget The second target value in linear space.
* @param rate The convergence rate in units per second, or 0 to set the value immediately.
* @return True if either target differs from the previous target.
*/
- public boolean animateTo(float firstTarget, float secondTarget, float rate) {
- final boolean firstRetval = mFirst.animateTo(firstTarget, rate);
- final boolean secondRetval = mSecond.animateTo(secondTarget, rate);
+ public boolean animateTo(float linearFirstTarget, float linearSecondTarget, float rate) {
+ final boolean firstRetval = mFirst.animateTo(linearFirstTarget, rate);
+ final boolean secondRetval = mSecond.animateTo(linearSecondTarget, rate);
return firstRetval && secondRetval;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 211f8d6..f3562d6 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -658,7 +658,14 @@
return mBuffer.descendingIterator();
}
- public StatusBarNotification[] getArray(int count, boolean includeSnoozed) {
+ public StatusBarNotification[] getArray(UserManager um, int count, boolean includeSnoozed) {
+ ArrayList<Integer> currentUsers = new ArrayList<>();
+ currentUsers.add(UserHandle.USER_ALL);
+ Binder.withCleanCallingIdentity(() -> {
+ for (int user : um.getProfileIds(ActivityManager.getCurrentUser(), false)) {
+ currentUsers.add(user);
+ }
+ });
synchronized (mBufferLock) {
if (count == 0) count = mBufferSize;
List<StatusBarNotification> a = new ArrayList();
@@ -667,8 +674,10 @@
while (iter.hasNext() && i < count) {
Pair<StatusBarNotification, Integer> pair = iter.next();
if (pair.second != REASON_SNOOZED || includeSnoozed) {
- i++;
- a.add(pair.first);
+ if (currentUsers.contains(pair.first.getUserId())) {
+ i++;
+ a.add(pair.first);
+ }
}
}
return a.toArray(new StatusBarNotification[a.size()]);
@@ -4042,22 +4051,32 @@
android.Manifest.permission.ACCESS_NOTIFICATIONS,
"NotificationManagerService.getActiveNotifications");
- StatusBarNotification[] tmp = null;
+ ArrayList<StatusBarNotification> tmp = new ArrayList<>();
int uid = Binder.getCallingUid();
+ ArrayList<Integer> currentUsers = new ArrayList<>();
+ currentUsers.add(UserHandle.USER_ALL);
+ Binder.withCleanCallingIdentity(() -> {
+ for (int user : mUm.getProfileIds(ActivityManager.getCurrentUser(), false)) {
+ currentUsers.add(user);
+ }
+ });
+
// noteOp will check to make sure the callingPkg matches the uid
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
callingAttributionTag, null)
== AppOpsManager.MODE_ALLOWED) {
synchronized (mNotificationLock) {
- tmp = new StatusBarNotification[mNotificationList.size()];
final int N = mNotificationList.size();
- for (int i=0; i<N; i++) {
- tmp[i] = mNotificationList.get(i).getSbn();
+ for (int i = 0; i < N; i++) {
+ final StatusBarNotification sbn = mNotificationList.get(i).getSbn();
+ if (currentUsers.contains(sbn.getUserId())) {
+ tmp.add(sbn);
+ }
}
}
}
- return tmp;
+ return tmp.toArray(new StatusBarNotification[tmp.size()]);
}
/**
@@ -4166,7 +4185,7 @@
callingAttributionTag, null)
== AppOpsManager.MODE_ALLOWED) {
synchronized (mArchive) {
- tmp = mArchive.getArray(count, includeSnoozed);
+ tmp = mArchive.getArray(mUm, count, includeSnoozed);
}
}
return tmp;
@@ -7695,7 +7714,9 @@
int index = mToastQueue.indexOf(record);
if (index >= 0) {
- mToastQueue.remove(index);
+ ToastRecord toast = mToastQueue.remove(index);
+ mWindowManagerInternal.removeWindowToken(
+ toast.windowToken, true /* removeWindows */, toast.displayId);
}
record = (mToastQueue.size() > 0) ? mToastQueue.get(0) : null;
}
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index 4d19855..acbe04b 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -24,11 +24,14 @@
import android.content.ComponentName;
import android.content.Context;
import android.media.AudioAttributes;
+import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings.Global;
import android.service.notification.ZenModeConfig;
import android.telecom.TelecomManager;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.Slog;
@@ -36,6 +39,8 @@
import com.android.internal.util.NotificationMessagingUtil;
import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
import java.util.Date;
public class ZenModeFiltering {
@@ -64,13 +69,22 @@
pw.print(prefix); pw.print("RepeatCallers.mThresholdMinutes=");
pw.println(REPEAT_CALLERS.mThresholdMinutes);
synchronized (REPEAT_CALLERS) {
- if (!REPEAT_CALLERS.mCalls.isEmpty()) {
- pw.print(prefix); pw.println("RepeatCallers.mCalls=");
- for (int i = 0; i < REPEAT_CALLERS.mCalls.size(); i++) {
+ if (!REPEAT_CALLERS.mTelCalls.isEmpty()) {
+ pw.print(prefix); pw.println("RepeatCallers.mTelCalls=");
+ for (int i = 0; i < REPEAT_CALLERS.mTelCalls.size(); i++) {
pw.print(prefix); pw.print(" ");
- pw.print(REPEAT_CALLERS.mCalls.keyAt(i));
+ pw.print(REPEAT_CALLERS.mTelCalls.keyAt(i));
pw.print(" at ");
- pw.println(ts(REPEAT_CALLERS.mCalls.valueAt(i)));
+ pw.println(ts(REPEAT_CALLERS.mTelCalls.valueAt(i)));
+ }
+ }
+ if (!REPEAT_CALLERS.mOtherCalls.isEmpty()) {
+ pw.print(prefix); pw.println("RepeatCallers.mOtherCalls=");
+ for (int i = 0; i < REPEAT_CALLERS.mOtherCalls.size(); i++) {
+ pw.print(prefix); pw.print(" ");
+ pw.print(REPEAT_CALLERS.mOtherCalls.keyAt(i));
+ pw.print(" at ");
+ pw.println(ts(REPEAT_CALLERS.mOtherCalls.valueAt(i)));
}
}
}
@@ -312,34 +326,39 @@
}
private static class RepeatCallers {
- // Person : time
- private final ArrayMap<String, Long> mCalls = new ArrayMap<>();
+ // We keep a separate map per uri scheme to do more generous number-matching
+ // handling on telephone numbers specifically. For other inputs, we
+ // simply match directly on the string.
+ private final ArrayMap<String, Long> mTelCalls = new ArrayMap<>();
+ private final ArrayMap<String, Long> mOtherCalls = new ArrayMap<>();
private int mThresholdMinutes;
private synchronized void recordCall(Context context, Bundle extras) {
setThresholdMinutes(context);
if (mThresholdMinutes <= 0 || extras == null) return;
- final String peopleString = peopleString(extras);
- if (peopleString == null) return;
+ final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
+ if (extraPeople == null || extraPeople.length == 0) return;
final long now = System.currentTimeMillis();
- cleanUp(mCalls, now);
- mCalls.put(peopleString, now);
+ cleanUp(mTelCalls, now);
+ cleanUp(mOtherCalls, now);
+ recordCallers(extraPeople, now);
}
private synchronized boolean isRepeat(Context context, Bundle extras) {
setThresholdMinutes(context);
if (mThresholdMinutes <= 0 || extras == null) return false;
- final String peopleString = peopleString(extras);
- if (peopleString == null) return false;
+ final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
+ if (extraPeople == null || extraPeople.length == 0) return false;
final long now = System.currentTimeMillis();
- cleanUp(mCalls, now);
- return mCalls.containsKey(peopleString);
+ cleanUp(mTelCalls, now);
+ cleanUp(mOtherCalls, now);
+ return checkCallers(context, extraPeople);
}
private synchronized void cleanUp(ArrayMap<String, Long> calls, long now) {
final int N = calls.size();
for (int i = N - 1; i >= 0; i--) {
- final long time = mCalls.valueAt(i);
+ final long time = calls.valueAt(i);
if (time > now || (now - time) > mThresholdMinutes * 1000 * 60) {
calls.removeAt(i);
}
@@ -353,21 +372,65 @@
}
}
- private static String peopleString(Bundle extras) {
- final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
- if (extraPeople == null || extraPeople.length == 0) return null;
- final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < extraPeople.length; i++) {
- String extraPerson = extraPeople[i];
- if (extraPerson == null) continue;
- extraPerson = extraPerson.trim();
- if (extraPerson.isEmpty()) continue;
- if (sb.length() > 0) {
- sb.append('|');
+ private synchronized void recordCallers(String[] people, long now) {
+ for (int i = 0; i < people.length; i++) {
+ String person = people[i];
+ if (person == null) continue;
+ final Uri uri = Uri.parse(person);
+ if ("tel".equals(uri.getScheme())) {
+ String tel = uri.getSchemeSpecificPart();
+ // while ideally we should not need to do this, sometimes we have seen tel
+ // numbers given in a url-encoded format
+ try {
+ tel = URLDecoder.decode(tel, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // ignore, keep the original tel string
+ Slog.w(TAG, "unsupported encoding in tel: uri input");
+ }
+ mTelCalls.put(tel, now);
+ } else {
+ // for non-tel calls, store the entire string, uri-component and all
+ mOtherCalls.put(person, now);
}
- sb.append(extraPerson);
}
- return sb.length() == 0 ? null : sb.toString();
+ }
+
+ private synchronized boolean checkCallers(Context context, String[] people) {
+ // get the default country code for checking telephone numbers
+ final String defaultCountryCode =
+ context.getSystemService(TelephonyManager.class).getNetworkCountryIso();
+ for (int i = 0; i < people.length; i++) {
+ String person = people[i];
+ if (person == null) continue;
+ final Uri uri = Uri.parse(person);
+ if ("tel".equals(uri.getScheme())) {
+ String number = uri.getSchemeSpecificPart();
+ if (mTelCalls.containsKey(number)) {
+ // check directly via map first
+ return true;
+ } else {
+ // see if a number that matches via areSameNumber exists
+ String numberToCheck = number;
+ try {
+ numberToCheck = URLDecoder.decode(number, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // ignore, continue to use the original string
+ Slog.w(TAG, "unsupported encoding in tel: uri input");
+ }
+ for (String prev : mTelCalls.keySet()) {
+ if (PhoneNumberUtils.areSamePhoneNumber(
+ numberToCheck, prev, defaultCountryCode)) {
+ return true;
+ }
+ }
+ }
+ } else {
+ if (mOtherCalls.containsKey(person)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 419b726..24b9f48 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -815,7 +815,7 @@
PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
int flags, Bundle options, String ownerPackage, int ownerUserId) {
return mActivityManagerInternal.getPendingIntentActivityAsApp(requestCode, intents,
- flags, options, ownerPackage, ownerUserId);
+ flags, null /* options */, ownerPackage, ownerUserId);
}
@Override
@@ -1117,7 +1117,7 @@
// calling identity to mirror the startActivityAsUser() call which does not validate
// the calling user
return PendingIntent.getActivityAsUser(mContext, 0 /* requestCode */, launchIntent,
- FLAG_IMMUTABLE, opts, user);
+ FLAG_IMMUTABLE, null /* options */, user);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 26aebbc..851ef08 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -116,6 +116,7 @@
import com.android.server.pm.verify.domain.DomainVerificationLegacySettings;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.DomainVerificationPersistence;
+import com.android.server.utils.Slogf;
import com.android.server.utils.Snappable;
import com.android.server.utils.SnapshotCache;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -944,7 +945,8 @@
Slog.i(PackageManagerService.TAG, "Stopping package " + pkgName, e);
}
List<UserInfo> users = getAllUsers(userManager);
- final int installUserId = installUser != null ? installUser.getIdentifier() : 0;
+ int installUserId = installUser != null ? installUser.getIdentifier()
+ : UserHandle.USER_SYSTEM;
if (users != null && allowInstall) {
for (UserInfo user : users) {
// By default we consider this app to be installed
@@ -955,8 +957,14 @@
// user we are installing for.
final boolean installed = installUser == null
|| (installUserId == UserHandle.USER_ALL
- && !isAdbInstallDisallowed(userManager, user.id))
+ && !isAdbInstallDisallowed(userManager, user.id)
+ && !user.preCreated)
|| installUserId == user.id;
+ if (DEBUG_MU) {
+ Slogf.d(TAG, "createNewSetting(pkg=%s, installUserId=%s, user=%s, "
+ + "installed=%b)",
+ pkgName, installUserId, user.toFullString(), installed);
+ }
pkgSetting.setUserState(user.id, 0, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
true /*stopped*/,
@@ -1980,11 +1988,14 @@
serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
- if (DEBUG_MU) Log.i(TAG, "Writing " + userPackagesStateFile);
+ if (DEBUG_MU) {
+ Slogf.i(TAG, "Writing %s (%d packages)", userPackagesStateFile,
+ mPackages.values().size());
+ }
for (final PackageSetting pkg : mPackages.values()) {
final PackageUserState ustate = pkg.readUserState(userId);
if (DEBUG_MU) {
- Log.i(TAG, " pkg=" + pkg.name + ", installed=" + ustate.installed
+ Log.v(TAG, " pkg=" + pkg.name + ", installed=" + ustate.installed
+ ", state=" + ustate.enabled);
}
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 51c3b33..748f644 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -78,6 +78,7 @@
import android.os.Process;
import android.os.SystemClock;
import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.util.Slog;
@@ -99,6 +100,7 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
+import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -161,6 +163,14 @@
public class VcnGatewayConnection extends StateMachine {
private static final String TAG = VcnGatewayConnection.class.getSimpleName();
+ // Matches DataConnection.NETWORK_TYPE private constant, and magic string from
+ // ConnectivityManager#getNetworkTypeName()
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final String NETWORK_INFO_NETWORK_TYPE_STRING = "MOBILE";
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final String NETWORK_INFO_EXTRA_INFO = "VCN";
+
@VisibleForTesting(visibility = Visibility.PRIVATE)
static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0");
@@ -1624,6 +1634,12 @@
final NetworkAgentConfig nac =
new NetworkAgentConfig.Builder()
.setLegacyType(ConnectivityManager.TYPE_MOBILE)
+ .setLegacyTypeName(NETWORK_INFO_NETWORK_TYPE_STRING)
+ .setLegacySubType(TelephonyManager.NETWORK_TYPE_UNKNOWN)
+ .setLegacySubTypeName(
+ TelephonyManager.getNetworkTypeName(
+ TelephonyManager.NETWORK_TYPE_UNKNOWN))
+ .setLegacyExtraInfo(NETWORK_INFO_EXTRA_INFO)
.build();
final VcnNetworkAgent agent =
@@ -2061,7 +2077,8 @@
return builder.build();
}
- private static LinkProperties buildConnectedLinkProperties(
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ LinkProperties buildConnectedLinkProperties(
@NonNull VcnGatewayConnectionConfig gatewayConnectionConfig,
@NonNull IpSecTunnelInterface tunnelIface,
@NonNull VcnChildSessionConfiguration childConfig,
@@ -2089,6 +2106,13 @@
lp.setTcpBufferSizes(underlyingLp.getTcpBufferSizes());
underlyingMtu = underlyingLp.getMtu();
+
+ // WiFi LinkProperties uses DHCP as the sole source of MTU information, and as a result
+ // often lists MTU as 0 (see b/184678973). Use the interface MTU as retrieved by
+ // NetworkInterface APIs.
+ if (underlyingMtu == 0 && underlyingLp.getInterfaceName() != null) {
+ underlyingMtu = mDeps.getUnderlyingIfaceMtu(underlyingLp.getInterfaceName());
+ }
} else {
Slog.wtf(
TAG,
@@ -2436,6 +2460,17 @@
public long getElapsedRealTime() {
return SystemClock.elapsedRealtime();
}
+
+ /** Gets the MTU for the given underlying interface. */
+ public int getUnderlyingIfaceMtu(String ifaceName) {
+ try {
+ final NetworkInterface underlyingIface = NetworkInterface.getByName(ifaceName);
+ return underlyingIface == null ? 0 : underlyingIface.getMTU();
+ } catch (IOException e) {
+ Slog.d(TAG, "Could not get MTU of underlying network", e);
+ return 0;
+ }
+ }
}
/**
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index a87b513..532590e 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1115,17 +1115,18 @@
env->NewObject(class_gnssAntennaInfoBuilder, method_gnssAntennaInfoBuilderCtor);
// Set fields
- env->CallObjectMethod(gnssAntennaInfoBuilderObject,
- method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz,
- gnssAntennaInfo.carrierFrequencyMHz);
- env->CallObjectMethod(gnssAntennaInfoBuilderObject,
- method_gnssAntennaInfoBuilderSetPhaseCenterOffset, phaseCenterOffset);
- env->CallObjectMethod(gnssAntennaInfoBuilderObject,
- method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections,
- phaseCenterVariationCorrections);
- env->CallObjectMethod(gnssAntennaInfoBuilderObject,
- method_gnssAntennaInfoBuilderSetSignalGainCorrections,
- signalGainCorrections);
+ callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject,
+ method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz,
+ gnssAntennaInfo.carrierFrequencyMHz);
+ callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject,
+ method_gnssAntennaInfoBuilderSetPhaseCenterOffset,
+ phaseCenterOffset);
+ callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject,
+ method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections,
+ phaseCenterVariationCorrections);
+ callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject,
+ method_gnssAntennaInfoBuilderSetSignalGainCorrections,
+ signalGainCorrections);
// build
jobject gnssAntennaInfoObject =
@@ -2707,7 +2708,7 @@
jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEplUnc);
uint16_t corrFlags = static_cast<uint16_t>(correctionFlags);
- jobject reflectingPlaneObj;
+ jobject reflectingPlaneObj = nullptr;
bool has_ref_plane = (corrFlags & GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE) != 0;
if (has_ref_plane) {
reflectingPlaneObj =
@@ -2731,6 +2732,7 @@
.azimuthDegrees = azimuthDegreeRefPlane,
};
}
+ env->DeleteLocalRef(reflectingPlaneObj);
SingleSatCorrection_V1_0 singleSatCorrection = {
.singleSatCorrectionFlags = corrFlags,
@@ -2762,6 +2764,7 @@
};
list[i] = singleSatCorrection_1_1;
+ env->DeleteLocalRef(singleSatCorrectionObj);
}
}
@@ -2779,6 +2782,7 @@
singleSatCorrection.constellation = static_cast<GnssConstellationType_V1_0>(constType),
list[i] = singleSatCorrection;
+ env->DeleteLocalRef(singleSatCorrectionObj);
}
}
@@ -2849,6 +2853,7 @@
hidl_vec<SingleSatCorrection_V1_0> list(len);
getSingleSatCorrectionList_1_0(env, singleSatCorrectionList, list);
+ env->DeleteLocalRef(singleSatCorrectionList);
measurementCorrections_1_0.satCorrections = list;
auto result = gnssCorrectionsIface_V1_0->setCorrections(measurementCorrections_1_0);
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
index 8c6c673..de99dce 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.cpp
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -335,24 +335,24 @@
satellitePvt.satClockInfo.satHardwareCodeBiasMeters,
satellitePvt.satClockInfo.satTimeCorrectionMeters,
satellitePvt.satClockInfo.satClkDriftMps);
- env->CallObjectMethod(satellitePvtBuilderObject,
- method_satellitePvtBuilderSetPositionEcef, positionEcef);
- env->CallObjectMethod(satellitePvtBuilderObject,
- method_satellitePvtBuilderSetVelocityEcef, velocityEcef);
- env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderSetClockInfo,
- clockInfo);
+ callObjectMethodIgnoringResult(env, satellitePvtBuilderObject,
+ method_satellitePvtBuilderSetPositionEcef, positionEcef);
+ callObjectMethodIgnoringResult(env, satellitePvtBuilderObject,
+ method_satellitePvtBuilderSetVelocityEcef, velocityEcef);
+ callObjectMethodIgnoringResult(env, satellitePvtBuilderObject,
+ method_satellitePvtBuilderSetClockInfo, clockInfo);
}
if (satFlags & SatellitePvt::HAS_IONO) {
- env->CallObjectMethod(satellitePvtBuilderObject,
- method_satellitePvtBuilderSetIonoDelayMeters,
- satellitePvt.ionoDelayMeters);
+ callObjectMethodIgnoringResult(env, satellitePvtBuilderObject,
+ method_satellitePvtBuilderSetIonoDelayMeters,
+ satellitePvt.ionoDelayMeters);
}
if (satFlags & SatellitePvt::HAS_TROPO) {
- env->CallObjectMethod(satellitePvtBuilderObject,
- method_satellitePvtBuilderSetTropoDelayMeters,
- satellitePvt.tropoDelayMeters);
+ callObjectMethodIgnoringResult(env, satellitePvtBuilderObject,
+ method_satellitePvtBuilderSetTropoDelayMeters,
+ satellitePvt.tropoDelayMeters);
}
jobject satellitePvtObject =
@@ -380,17 +380,19 @@
jobject correlationVectorBuilderObject =
env->NewObject(class_correlationVectorBuilder,
method_correlationVectorBuilderCtor);
- env->CallObjectMethod(correlationVectorBuilderObject,
- method_correlationVectorBuilderSetMagnitude, magnitudeArray);
- env->CallObjectMethod(correlationVectorBuilderObject,
- method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond,
- correlationVector.frequencyOffsetMps);
- env->CallObjectMethod(correlationVectorBuilderObject,
- method_correlationVectorBuilderSetSamplingStartMeters,
- correlationVector.samplingStartM);
- env->CallObjectMethod(correlationVectorBuilderObject,
- method_correlationVectorBuilderSetSamplingWidthMeters,
- correlationVector.samplingWidthM);
+ callObjectMethodIgnoringResult(env, correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetMagnitude,
+ magnitudeArray);
+ callObjectMethodIgnoringResult(
+ env, correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond,
+ correlationVector.frequencyOffsetMps);
+ callObjectMethodIgnoringResult(env, correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetSamplingStartMeters,
+ correlationVector.samplingStartM);
+ callObjectMethodIgnoringResult(env, correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetSamplingWidthMeters,
+ correlationVector.samplingWidthM);
jobject correlationVectorObject =
env->CallObjectMethod(correlationVectorBuilderObject,
method_correlationVectorBuilderBuild);
diff --git a/services/core/jni/gnss/Utils.cpp b/services/core/jni/gnss/Utils.cpp
index 20e14a9..08a0888 100644
--- a/services/core/jni/gnss/Utils.cpp
+++ b/services/core/jni/gnss/Utils.cpp
@@ -82,6 +82,13 @@
}
}
+void callObjectMethodIgnoringResult(JNIEnv* env, jobject obj, jmethodID mid, ...) {
+ va_list args;
+ va_start(args, mid);
+ env->DeleteLocalRef(env->CallObjectMethodV(obj, mid, args));
+ va_end(args);
+}
+
JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor)
: env_(env), clazz_(clazz) {
object_ = env_->NewObject(clazz_, defaultCtor);
diff --git a/services/core/jni/gnss/Utils.h b/services/core/jni/gnss/Utils.h
index 0938a1b..52e2b20 100644
--- a/services/core/jni/gnss/Utils.h
+++ b/services/core/jni/gnss/Utils.h
@@ -48,6 +48,8 @@
void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
+void callObjectMethodIgnoringResult(JNIEnv* env, jobject obj, jmethodID mid, ...);
+
template <class T>
void logHidlError(hardware::Return<T>& result, const char* errorMessage) {
ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str());
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 429edf1..a98483c 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -34,7 +34,8 @@
<xs:annotation name="nonnull"/>
<xs:annotation name="final"/>
</xs:element>
- <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0" maxOccurs="1"/>
+ <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0"
+ maxOccurs="1"/>
<xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1" />
<xs:element type="nonNegativeDecimal" name="screenBrightnessRampFastDecrease">
<xs:annotation name="final"/>
@@ -54,6 +55,19 @@
<xs:element type="sensorDetails" name="proxSensor">
<xs:annotation name="final"/>
</xs:element>
+
+ <!-- Set of thresholds that dictate the change needed for screen brightness
+ adaptations -->
+ <xs:element type="thresholds" name="displayBrightnessChangeThresholds">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <!-- Set of thresholds that dictate the change needed for ambient brightness
+ adaptations -->
+ <xs:element type="thresholds" name="ambientBrightnessChangeThresholds">
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
@@ -68,7 +82,8 @@
<xs:complexType name="highBrightnessMode">
<xs:all>
- <xs:element name="transitionPoint" type="nonNegativeDecimal" minOccurs="1" maxOccurs="1">
+ <xs:element name="transitionPoint" type="nonNegativeDecimal" minOccurs="1"
+ maxOccurs="1">
<xs:annotation name="nonnull"/>
<xs:annotation name="final"/>
</xs:element>
@@ -97,7 +112,8 @@
<xs:complexType name="hbmTiming">
<xs:all>
- <xs:element name="timeWindowSecs" type="xs:nonNegativeInteger" minOccurs="1" maxOccurs="1">
+ <xs:element name="timeWindowSecs" type="xs:nonNegativeInteger" minOccurs="1"
+ maxOccurs="1">
<xs:annotation name="nonnull"/>
<xs:annotation name="final"/>
</xs:element>
@@ -181,5 +197,31 @@
</xs:sequence>
</xs:complexType>
+ <!-- Thresholds for brightness changes. -->
+ <xs:complexType name="thresholds">
+ <xs:sequence>
+ <!-- Brightening thresholds. -->
+ <xs:element name="brighteningThresholds" type="brightnessThresholds" minOccurs="0"
+ maxOccurs="1" >
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ <!-- Darkening thresholds. -->
+ <xs:element name="darkeningThresholds" type="brightnessThresholds" minOccurs="0"
+ maxOccurs="1" >
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <!-- Brightening and darkening minimum change thresholds. -->
+ <xs:complexType name="brightnessThresholds">
+ <!-- Minimum brightness change needed. -->
+ <xs:element name="minimum" type="nonNegativeDecimal" minOccurs="0" maxOccurs="1" >
+ <xs:annotation name="nonnull"/>
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:complexType>
</xs:schema>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index ad18602..df468d4 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -1,8 +1,16 @@
// Signature format: 2.0
package com.android.server.display.config {
+ public class BrightnessThresholds {
+ ctor public BrightnessThresholds();
+ method @NonNull public final java.math.BigDecimal getMinimum();
+ method public final void setMinimum(@NonNull java.math.BigDecimal);
+ }
+
public class DisplayConfiguration {
ctor public DisplayConfiguration();
+ method @NonNull public final com.android.server.display.config.Thresholds getAmbientBrightnessChangeThresholds();
+ method @NonNull public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholds();
method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode();
method public final com.android.server.display.config.SensorDetails getLightSensor();
method public final com.android.server.display.config.SensorDetails getProxSensor();
@@ -13,6 +21,8 @@
method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease();
method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
+ method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds);
+ method public final void setDisplayBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds);
method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode);
method public final void setLightSensor(com.android.server.display.config.SensorDetails);
method public final void setProxSensor(com.android.server.display.config.SensorDetails);
@@ -100,6 +110,14 @@
enum_constant public static final com.android.server.display.config.ThermalStatus shutdown;
}
+ public class Thresholds {
+ ctor public Thresholds();
+ method @NonNull public final com.android.server.display.config.BrightnessThresholds getBrighteningThresholds();
+ method @NonNull public final com.android.server.display.config.BrightnessThresholds getDarkeningThresholds();
+ method public final void setBrighteningThresholds(@NonNull com.android.server.display.config.BrightnessThresholds);
+ method public final void setDarkeningThresholds(@NonNull com.android.server.display.config.BrightnessThresholds);
+ }
+
public class XmlParser {
ctor public XmlParser();
method public static com.android.server.display.config.DisplayConfiguration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d681f69..a46ae27 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -10763,7 +10763,7 @@
}
@Override
- public void resetNewUserDisclaimer() {
+ public void acknowledgeNewUserDisclaimer() {
CallerIdentity callerIdentity = getCallerIdentity();
canManageUsers(callerIdentity);
diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
index cffff66..02cf971 100644
--- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
@@ -23,7 +23,14 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.debug.AdbManager;
+import android.debug.IAdbManager;
+import android.os.ServiceManager;
import android.provider.Settings;
import android.util.Log;
@@ -105,6 +112,7 @@
public void tearDown() throws Exception {
mKeyStore.deleteKeyStore();
setAllowedConnectionTime(mOriginalAllowedConnectionTime);
+ dropShellPermissionIdentity();
}
/**
@@ -813,6 +821,108 @@
return hasAtLeastOneLetter;
}
+ CountDownLatch mAdbActionLatch = new CountDownLatch(1);
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ Log.i(TAG, "Received intent action=" + action);
+ if (AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ Log.i(TAG, "action=" + action + " paired_device=" + intent.getSerializableExtra(
+ AdbManager.WIRELESS_DEVICES_EXTRA).toString());
+ mAdbActionLatch.countDown();
+ } else if (AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ int status = intent.getIntExtra(AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_DISCONNECTED);
+ Log.i(TAG, "action=" + action + " status=" + status);
+ mAdbActionLatch.countDown();
+ } else if (AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ Integer res = intent.getIntExtra(
+ AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_FAIL);
+ Log.i(TAG, "action=" + action + " result=" + res);
+
+ if (res.equals(AdbManager.WIRELESS_STATUS_PAIRING_CODE)) {
+ String pairingCode = intent.getStringExtra(
+ AdbManager.WIRELESS_PAIRING_CODE_EXTRA);
+ Log.i(TAG, "pairingCode=" + pairingCode);
+ } else if (res.equals(AdbManager.WIRELESS_STATUS_CONNECTED)) {
+ int port = intent.getIntExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, 0);
+ Log.i(TAG, "port=" + port);
+ }
+ mAdbActionLatch.countDown();
+ }
+ }
+ };
+
+ private void adoptShellPermissionIdentity() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.MANAGE_DEBUGGING);
+ }
+
+ private void dropShellPermissionIdentity() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ @Test
+ public void testBroadcastReceiverWithPermissions() throws Exception {
+ adoptShellPermissionIdentity();
+ final IAdbManager mAdbManager = IAdbManager.Stub.asInterface(
+ ServiceManager.getService(Context.ADB_SERVICE));
+ IntentFilter intentFilter =
+ new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ assertEquals("Context does not have MANAGE_DEBUGGING permission.",
+ mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ try {
+ mContext.registerReceiver(mReceiver, intentFilter);
+ mAdbManager.enablePairingByPairingCode();
+ if (!mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+ fail("Receiver did not receive adb intent action within the timeout duration");
+ }
+ } finally {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ @Test
+ public void testBroadcastReceiverWithoutPermissions() throws Exception {
+ adoptShellPermissionIdentity();
+ final IAdbManager mAdbManager = IAdbManager.Stub.asInterface(
+ ServiceManager.getService(Context.ADB_SERVICE));
+ IntentFilter intentFilter =
+ new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ mAdbManager.enablePairingByPairingCode();
+
+ dropShellPermissionIdentity();
+ assertEquals("Context has MANAGE_DEBUGGING permission.",
+ mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_DENIED);
+ try {
+ mContext.registerReceiver(mReceiver, intentFilter);
+
+ if (mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+ fail("Broadcast receiver received adb action intent without debug permissions");
+ }
+ } finally {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
/**
* Runs an adb test with the provided configuration.
*
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index bdf94f3..356600d 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -33,6 +33,7 @@
import android.content.IntentFilter;
import android.content.pm.ParceledListSlice;
import android.database.ContentObserver;
+import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.display.AmbientBrightnessDayStats;
@@ -42,6 +43,7 @@
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
+import android.hardware.input.InputSensorInfo;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.HandlerThread;
@@ -63,6 +65,8 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -84,8 +88,11 @@
private static final String DEFAULT_DISPLAY_ID = "123";
private static final float FLOAT_DELTA = 0.01f;
+ @Mock private InputSensorInfo mInputSensorInfoMock;
+
private BrightnessTracker mTracker;
private TestInjector mInjector;
+ private Sensor mLightSensorFake;
private static Object sHandlerLock = new Object();
private static Handler sHandler;
@@ -108,9 +115,12 @@
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
mInjector = new TestInjector(ensureHandler());
+ mLightSensorFake = new Sensor(mInputSensorInfoMock);
mTracker = new BrightnessTracker(InstrumentationRegistry.getContext(), mInjector);
+ mTracker.setLightSensor(mLightSensorFake);
mDefaultNightModeColorTemperature =
InstrumentationRegistry.getContext().getResources().getInteger(
R.integer.config_nightDisplayColorTemperatureDefault);
@@ -834,6 +844,47 @@
mTracker.stop();
}
+ @Test
+ public void testLightSensorChange() {
+ // verify the tracker started correctly and a listener registered
+ startTracker(mTracker);
+ assertNotNull(mInjector.mSensorListener);
+ assertEquals(mInjector.mLightSensor, mLightSensorFake);
+
+ // Setting the sensor to null should stop the registered listener.
+ mTracker.setLightSensor(null);
+ mInjector.waitForHandler();
+ assertNull(mInjector.mSensorListener);
+ assertNull(mInjector.mLightSensor);
+
+ // Resetting sensor should start listener again
+ mTracker.setLightSensor(mLightSensorFake);
+ mInjector.waitForHandler();
+ assertNotNull(mInjector.mSensorListener);
+ assertEquals(mInjector.mLightSensor, mLightSensorFake);
+
+ Sensor secondSensor = new Sensor(mInputSensorInfoMock);
+ // Setting a different listener should keep things working
+ mTracker.setLightSensor(secondSensor);
+ mInjector.waitForHandler();
+ assertNotNull(mInjector.mSensorListener);
+ assertEquals(mInjector.mLightSensor, secondSensor);
+ }
+
+ @Test
+ public void testSetLightSensorDoesntStartListener() {
+ mTracker.setLightSensor(mLightSensorFake);
+ assertNull(mInjector.mSensorListener);
+ }
+
+ @Test
+ public void testNullLightSensorWontRegister() {
+ mTracker.setLightSensor(null);
+ startTracker(mTracker);
+ assertNull(mInjector.mSensorListener);
+ assertNull(mInjector.mLightSensor);
+ }
+
private InputStream getInputStream(String data) {
return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
}
@@ -924,6 +975,7 @@
private class TestInjector extends BrightnessTracker.Injector {
SensorEventListener mSensorListener;
+ Sensor mLightSensor;
BroadcastReceiver mBroadcastReceiver;
DisplayManager.DisplayListener mDisplayListener;
Map<String, Integer> mSecureIntSettings = new HashMap<>();
@@ -974,14 +1026,16 @@
@Override
public void registerSensorListener(Context context,
- SensorEventListener sensorListener, Handler handler) {
+ SensorEventListener sensorListener, Sensor lightSensor, Handler handler) {
mSensorListener = sensorListener;
+ mLightSensor = lightSensor;
}
@Override
public void unregisterSensorListener(Context context,
SensorEventListener sensorListener) {
mSensorListener = null;
+ mLightSensor = null;
}
@Override
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
index 1126e1e..4b6183d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
@@ -15,16 +15,22 @@
*/
package com.android.server.notification;
+import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_CURRENT;
+import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
import android.app.Notification;
import android.os.UserHandle;
+import android.os.UserManager;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
@@ -35,6 +41,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -51,6 +58,8 @@
private static final int SIZE = 5;
private NotificationManagerService.Archive mArchive;
+ @Mock
+ private UserManager mUm;
@Before
public void setUp() {
@@ -59,6 +68,9 @@
mArchive = new NotificationManagerService.Archive(SIZE);
mArchive.updateHistoryEnabled(USER_SYSTEM, true);
mArchive.updateHistoryEnabled(USER_CURRENT, true);
+
+ when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(
+ new int[] {USER_CURRENT, USER_SYSTEM});
}
private StatusBarNotification getNotification(String pkg, int id, UserHandle user) {
@@ -70,7 +82,6 @@
pkg, pkg, id, null, 0, 0, n, user, null, System.currentTimeMillis());
}
-
@Test
public void testRecordAndRead() {
List<String> expected = new ArrayList<>();
@@ -81,7 +92,7 @@
mArchive.record(sbn, REASON_CANCEL);
}
- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
@@ -89,6 +100,22 @@
}
@Test
+ public void testCrossUser() {
+ mArchive.record(getNotification("pkg", 1, UserHandle.of(USER_SYSTEM)), REASON_CANCEL);
+ mArchive.record(getNotification("pkg", 2, UserHandle.of(USER_CURRENT)), REASON_CANCEL);
+ mArchive.record(getNotification("pkg", 3, UserHandle.of(USER_ALL)), REASON_CANCEL);
+ mArchive.record(getNotification("pkg", 4, UserHandle.of(USER_NULL)), REASON_CANCEL);
+
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
+ assertThat(actual).hasSize(3);
+ for (StatusBarNotification sbn : actual) {
+ if (sbn.getUserId() == USER_NULL) {
+ fail("leaked notification from wrong user");
+ }
+ }
+ }
+
+ @Test
public void testRecordAndRead_overLimit() {
List<String> expected = new ArrayList<>();
for (int i = 0; i < (SIZE * 2); i++) {
@@ -99,7 +126,8 @@
}
}
- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray((SIZE * 2), true));
+ List<StatusBarNotification> actual = Arrays.asList(
+ mArchive.getArray(mUm, (SIZE * 2), true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
@@ -119,7 +147,7 @@
}
}
- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
@@ -140,7 +168,7 @@
}
mArchive.updateHistoryEnabled(USER_CURRENT, false);
- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
@@ -165,7 +193,7 @@
}
mArchive.removeChannelNotifications("pkg", USER_CURRENT, "test0");
mArchive.removeChannelNotifications("pkg", USER_CURRENT, "test" + (SIZE - 2));
- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
@@ -215,7 +243,7 @@
fail("Concurrent modification exception");
}
- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index e98d077..b98401e 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -60,6 +60,7 @@
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.google.common.truth.Truth.assertThat;
@@ -475,6 +476,7 @@
when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
+ when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0});
// write to a test file; the system file isn't readable from tests
mFile = new File(mContext.getCacheDir(), "test.xml");
@@ -5572,6 +5574,39 @@
}
@Test
+ public void testRateLimitedToasts_windowsRemoved() throws Exception {
+ final String testPackage = "testPackageName";
+ assertEquals(0, mService.mToastQueue.size());
+ mService.isSystemUid = false;
+ setToastRateIsWithinQuota(false); // rate limit reached
+ setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false);
+ setAppInForegroundForToasts(mUid, false);
+
+ // package is not suspended
+ when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid)))
+ .thenReturn(false);
+
+ Binder token = new Binder();
+ INotificationManager nmService = (INotificationManager) mService.mService;
+
+ nmService.enqueueTextToast(testPackage, token, "Text", 2000, 0, null);
+
+ // window token was added when enqueued
+ ArgumentCaptor<Binder> binderCaptor =
+ ArgumentCaptor.forClass(Binder.class);
+ verify(mWindowManagerInternal).addWindowToken(binderCaptor.capture(),
+ eq(TYPE_TOAST), anyInt(), eq(null));
+
+ // but never shown
+ verify(mStatusBar, times(0))
+ .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any());
+
+ // and removed when rate limited
+ verify(mWindowManagerInternal)
+ .removeWindowToken(eq(binderCaptor.getValue()), eq(true), anyInt());
+ }
+
+ @Test
public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws
Exception {
final String testPackage = "testPackageName";
@@ -6970,8 +7005,9 @@
waitForIdle();
// A notification exists for the given record
- StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
- assertEquals(1, notifsBefore.length);
+ List<StatusBarNotification> notifsBefore =
+ mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList();
+ assertEquals(1, notifsBefore.size());
reset(mPackageManager);
@@ -8289,4 +8325,33 @@
assertTrue(captor.getValue().isPackageAllowed(new VersionedPackage("apples", 1001)));
assertFalse(captor.getValue().isPackageAllowed(new VersionedPackage("test", 1002)));
}
+
+ @Test
+ public void testGetActiveNotification_filtersUsers() throws Exception {
+ when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10});
+
+ NotificationRecord nr0 =
+ generateNotificationRecord(mTestNotificationChannel, 0);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0",
+ nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId());
+
+ NotificationRecord nr10 =
+ generateNotificationRecord(mTestNotificationChannel, 10);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10",
+ nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId());
+
+ NotificationRecord nr11 =
+ generateNotificationRecord(mTestNotificationChannel, 11);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11",
+ nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId());
+ waitForIdle();
+
+ StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
+ assertEquals(2, notifs.length);
+ for (StatusBarNotification sbn : notifs) {
+ if (sbn.getUserId() == 11) {
+ fail("leaked data across users");
+ }
+ }
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
index fb15088..0f18cc6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -17,7 +17,6 @@
package com.android.server.notification;
import static android.app.Notification.CATEGORY_CALL;
-import static android.app.Notification.CATEGORY_MESSAGE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
@@ -25,6 +24,7 @@
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
@@ -43,8 +43,10 @@
import android.app.NotificationChannel;
import android.app.NotificationManager.Policy;
import android.media.AudioAttributes;
+import android.os.Bundle;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
+import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -68,10 +70,15 @@
private NotificationMessagingUtil mMessagingUtil;
private ZenModeFiltering mZenModeFiltering;
+ @Mock private TelephonyManager mTelephonyManager;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mZenModeFiltering = new ZenModeFiltering(mContext, mMessagingUtil);
+
+ // for repeat callers / matchesCallFilter
+ mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
}
private NotificationRecord getNotificationRecord() {
@@ -95,6 +102,23 @@
return r;
}
+ private Bundle makeExtrasBundleWithPeople(String[] people) {
+ Bundle extras = new Bundle();
+ extras.putObject(Notification.EXTRA_PEOPLE_LIST, people);
+ return extras;
+ }
+
+ private NotificationRecord getNotificationRecordWithPeople(String[] people) {
+ // set up notification record
+ NotificationRecord r = mock(NotificationRecord.class);
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ Notification notification = mock(Notification.class);
+ notification.extras = makeExtrasBundleWithPeople(people);
+ when(sbn.getNotification()).thenReturn(notification);
+ when(r.getSbn()).thenReturn(sbn);
+ return r;
+ }
+
@Test
public void testIsMessage() {
NotificationRecord r = getNotificationRecord();
@@ -309,4 +333,111 @@
assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
}
+
+ @Test
+ public void testMatchesCallFilter_repeatCallers_directMatch() {
+ // after calls given an email with an exact string match, make sure that
+ // matchesCallFilter returns the right thing
+ String[] mailSource = new String[]{"mailto:hello.world"};
+ mZenModeFiltering.recordCall(getNotificationRecordWithPeople(mailSource));
+
+ // set up policy to only allow repeat callers
+ Policy policy = new Policy(
+ PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+ // check whether matchesCallFilter returns the right thing
+ Bundle inputMatches = makeExtrasBundleWithPeople(new String[]{"mailto:hello.world"});
+ Bundle inputWrong = makeExtrasBundleWithPeople(new String[]{"mailto:nope"});
+ assertTrue(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ inputMatches, null, 0, 0));
+ assertFalse(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ inputWrong, null, 0, 0));
+ }
+
+ @Test
+ public void testMatchesCallFilter_repeatCallers_telephoneVariants() {
+ // set up telephony manager behavior
+ when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
+
+ String[] telSource = new String[]{"tel:+1-617-555-1212"};
+ mZenModeFiltering.recordCall(getNotificationRecordWithPeople(telSource));
+
+ // set up policy to only allow repeat callers
+ Policy policy = new Policy(
+ PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+ // cases to test:
+ // - identical number
+ // - same number, different formatting
+ // - different number
+ // - garbage
+ Bundle identical = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
+ Bundle same = makeExtrasBundleWithPeople(new String[]{"tel:16175551212"});
+ Bundle different = makeExtrasBundleWithPeople(new String[]{"tel:123-456-7890"});
+ Bundle garbage = makeExtrasBundleWithPeople(new String[]{"asdfghjkl;"});
+
+ assertTrue("identical numbers should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ identical, null, 0, 0));
+ assertTrue("equivalent but non-identical numbers should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ same, null, 0, 0));
+ assertFalse("non-equivalent numbers should not match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ different, null, 0, 0));
+ assertFalse("non-tel strings should not match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ garbage, null, 0, 0));
+ }
+
+ @Test
+ public void testMatchesCallFilter_repeatCallers_urlEncodedTels() {
+ // this is not intended to be a supported case but is one that we have seen
+ // sometimes in the wild, so make sure we handle url-encoded telephone numbers correctly
+ // when somebody provides one.
+
+ // set up telephony manager behavior
+ when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
+
+ String[] telSource = new String[]{"tel:%2B16175551212"};
+ mZenModeFiltering.recordCall(getNotificationRecordWithPeople(telSource));
+
+ // set up policy to only allow repeat callers
+ Policy policy = new Policy(
+ PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+ // test cases for various forms of the same phone number and different ones
+ Bundle same1 = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
+ Bundle same2 = makeExtrasBundleWithPeople(new String[]{"tel:%2B1-617-555-1212"});
+ Bundle same3 = makeExtrasBundleWithPeople(new String[]{"tel:6175551212"});
+ Bundle different1 = makeExtrasBundleWithPeople(new String[]{"tel:%2B16175553434"});
+ Bundle different2 = makeExtrasBundleWithPeople(new String[]{"tel:+16175553434"});
+
+ assertTrue("same number should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ same1, null, 0, 0));
+ assertTrue("same number should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ same2, null, 0, 0));
+ assertTrue("same number should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ same3, null, 0, 0));
+ assertFalse("different number should not match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ different1, null, 0, 0));
+ assertFalse("different number should not match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ different2, null, 0, 0));
+ }
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 7b5f0b1..a687bb893 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -307,7 +307,10 @@
ncCaptor.capture(),
lpCaptor.capture(),
any(),
- argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE),
+ // Subtype integer/name and extras do not have getters; cannot be tested.
+ argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE
+ && nac.getLegacyTypeName().equals(
+ VcnGatewayConnection.NETWORK_INFO_NETWORK_TYPE_STRING)),
any(),
any(),
any());
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
index a700171..b8eefab 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
@@ -16,6 +16,7 @@
package com.android.server.vcn;
+import static android.net.IpSecManager.IpSecTunnelInterface;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
@@ -24,6 +25,8 @@
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
+import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
@@ -36,8 +39,11 @@
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.net.IpSecManager;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -59,8 +65,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.net.InetAddress;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -70,6 +79,8 @@
public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
private static final int TEST_UID = Process.myUid() + 1;
+ private static final String LOOPBACK_IFACE = "lo";
+
private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
private static final int TEST_SIM_SLOT_INDEX = 1;
private static final int TEST_SUBSCRIPTION_ID_1 = 2;
@@ -77,6 +88,12 @@
private static final int TEST_SUBSCRIPTION_ID_2 = 3;
private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;
+ private static final String TEST_TCP_BUFFER_SIZES = "1,2,3,4,5,6";
+ private static final int TEST_MTU = 1300;
+ private static final int TEST_MTU_DELTA = 64;
+ private static final List<LinkAddress> TEST_INTERNAL_ADDRESSES =
+ Arrays.asList(new LinkAddress(DUMMY_ADDR, 16));
+ private static final List<InetAddress> TEST_DNS_ADDRESSES = Arrays.asList(DUMMY_ADDR);
private static final int TEST_UPSTREAM_BANDWIDTH = 1234;
private static final int TEST_DOWNSTREAM_BANDWIDTH = 2345;
@@ -166,6 +183,59 @@
}
@Test
+ public void testBuildLinkProperties() throws Exception {
+ final IpSecTunnelInterface tunnelIface =
+ mContext.getSystemService(IpSecManager.class)
+ .createIpSecTunnelInterface(
+ DUMMY_ADDR, DUMMY_ADDR, TEST_UNDERLYING_NETWORK_RECORD_1.network);
+
+ final LinkProperties underlyingLp = new LinkProperties();
+ underlyingLp.setInterfaceName(LOOPBACK_IFACE);
+ underlyingLp.setTcpBufferSizes(TEST_TCP_BUFFER_SIZES);
+ doReturn(TEST_MTU).when(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE);
+
+ final VcnChildSessionConfiguration childSessionConfig =
+ mock(VcnChildSessionConfiguration.class);
+ doReturn(TEST_INTERNAL_ADDRESSES).when(childSessionConfig).getInternalAddresses();
+ doReturn(TEST_DNS_ADDRESSES).when(childSessionConfig).getInternalDnsServers();
+
+ UnderlyingNetworkRecord record =
+ new UnderlyingNetworkRecord(
+ mock(Network.class, CALLS_REAL_METHODS),
+ new NetworkCapabilities.Builder().build(),
+ underlyingLp,
+ false);
+
+ final LinkProperties vcnLp1 =
+ mGatewayConnection.buildConnectedLinkProperties(
+ VcnGatewayConnectionConfigTest.buildTestConfig(),
+ tunnelIface,
+ childSessionConfig,
+ record);
+
+ verify(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE);
+
+ // Instead of having to recalculate the final MTU (after accounting for IPsec overhead),
+ // calculate another set of Link Properties with a lower MTU, and calculate the delta.
+ doReturn(TEST_MTU - TEST_MTU_DELTA).when(mDeps).getUnderlyingIfaceMtu(LOOPBACK_IFACE);
+
+ final LinkProperties vcnLp2 =
+ mGatewayConnection.buildConnectedLinkProperties(
+ VcnGatewayConnectionConfigTest.buildTestConfig(),
+ tunnelIface,
+ childSessionConfig,
+ record);
+
+ verify(mDeps, times(2)).getUnderlyingIfaceMtu(LOOPBACK_IFACE);
+
+ assertEquals(tunnelIface.getInterfaceName(), vcnLp1.getInterfaceName());
+ assertEquals(TEST_INTERNAL_ADDRESSES, vcnLp1.getLinkAddresses());
+ assertEquals(TEST_DNS_ADDRESSES, vcnLp1.getDnsServers());
+ assertEquals(TEST_TCP_BUFFER_SIZES, vcnLp1.getTcpBufferSizes());
+ assertEquals(TEST_MTU_DELTA, vcnLp1.getMtu() - vcnLp2.getMtu());
+ }
+
+ @Test
public void testSubscriptionSnapshotUpdateNotifiesUnderlyingNetworkTracker() {
verifyWakeLockSetUp();