diff options
319 files changed, 4973 insertions, 2498 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index e8379205d55f..8b41aa4a7e7d 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -8468,8 +8468,8 @@ public class Notification implements Parcelable } int maxAvatarSize = resources.getDimensionPixelSize( - isLowRam ? R.dimen.notification_person_icon_max_size - : R.dimen.notification_person_icon_max_size_low_ram); + isLowRam ? R.dimen.notification_person_icon_max_size_low_ram + : R.dimen.notification_person_icon_max_size); if (mUser != null && mUser.getIcon() != null) { mUser.getIcon().scaleDownIfNecessary(maxAvatarSize, maxAvatarSize); } diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index 24e47bf9e47c..2dced96d3583 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -329,6 +329,22 @@ public class AppWidgetHost { } /** + * Set the visibiity of all widgets associated with this host to hidden + * + * @hide + */ + public void setAppWidgetHidden() { + if (sService == null) { + return; + } + try { + sService.setAppWidgetHidden(mContextOpPackageName, mHostId); + } catch (RemoteException e) { + throw new RuntimeException("System server dead?", e); + } + } + + /** * Set the host's interaction handler. * * @hide diff --git a/core/java/com/android/internal/app/AppLocaleCollector.java b/core/java/com/android/internal/app/AppLocaleCollector.java new file mode 100644 index 000000000000..65e8c646e17d --- /dev/null +++ b/core/java/com/android/internal/app/AppLocaleCollector.java @@ -0,0 +1,139 @@ +/* + * 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.internal.app; + +import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_ASSET; +import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG; + +import android.content.Context; +import android.os.Build; +import android.os.LocaleList; +import android.util.Log; + +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +/** The Locale data collector for per-app language. */ +class AppLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase { + private static final String TAG = AppLocaleCollector.class.getSimpleName(); + private final Context mContext; + private final String mAppPackageName; + private final LocaleStore.LocaleInfo mAppCurrentLocale; + + AppLocaleCollector(Context context, String appPackageName) { + mContext = context; + mAppPackageName = appPackageName; + mAppCurrentLocale = LocaleStore.getAppCurrentLocaleInfo( + mContext, mAppPackageName); + } + + @Override + public HashSet<String> getIgnoredLocaleList(boolean translatedOnly) { + HashSet<String> langTagsToIgnore = new HashSet<>(); + + LocaleList systemLangList = LocaleList.getDefault(); + for(int i = 0; i < systemLangList.size(); i++) { + langTagsToIgnore.add(systemLangList.get(i).toLanguageTag()); + } + + if (mAppCurrentLocale != null) { + langTagsToIgnore.add(mAppCurrentLocale.getLocale().toLanguageTag()); + } + return langTagsToIgnore; + } + + @Override + public Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, + boolean translatedOnly, boolean isForCountryMode) { + AppLocaleStore.AppLocaleResult result = + AppLocaleStore.getAppSupportedLocales(mContext, mAppPackageName); + Set<String> langTagsToIgnore = getIgnoredLocaleList(translatedOnly); + Set<LocaleStore.LocaleInfo> appLocaleList = new HashSet<>(); + Set<LocaleStore.LocaleInfo> systemLocaleList; + boolean shouldShowList = + result.mLocaleStatus == GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG + || result.mLocaleStatus == GET_SUPPORTED_LANGUAGE_FROM_ASSET; + + // Get system supported locale list + if (isForCountryMode) { + systemLocaleList = LocaleStore.getLevelLocales(mContext, + langTagsToIgnore, parent, translatedOnly); + } else { + systemLocaleList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, + null /* no parent */, translatedOnly); + } + + // Add current app locale + if (mAppCurrentLocale != null && !isForCountryMode) { + appLocaleList.add(mAppCurrentLocale); + } + + // Add current system language into suggestion list + for(LocaleStore.LocaleInfo localeInfo: + LocaleStore.getSystemCurrentLocaleInfo()) { + boolean isNotCurrentLocale = mAppCurrentLocale == null + || !localeInfo.getLocale().equals(mAppCurrentLocale.getLocale()); + if (!isForCountryMode && isNotCurrentLocale) { + appLocaleList.add(localeInfo); + } + } + + // Add the languages that included in system supported locale + if (shouldShowList) { + appLocaleList.addAll(filterTheLanguagesNotIncludedInSystemLocale( + systemLocaleList, result.mAppSupportedLocales)); + } + + // Add "system language" option + if (!isForCountryMode && shouldShowList) { + appLocaleList.add(LocaleStore.getSystemDefaultLocaleInfo( + mAppCurrentLocale == null)); + } + + if (Build.isDebuggable()) { + Log.d(TAG, "App locale list: " + appLocaleList); + } + + return appLocaleList; + } + + @Override + public boolean hasSpecificPackageName() { + return true; + } + + private Set<LocaleStore.LocaleInfo> filterTheLanguagesNotIncludedInSystemLocale( + Set<LocaleStore.LocaleInfo> systemLocaleList, + HashSet<Locale> appSupportedLocales) { + Set<LocaleStore.LocaleInfo> filteredList = new HashSet<>(); + + for(LocaleStore.LocaleInfo li: systemLocaleList) { + if (appSupportedLocales.contains(li.getLocale())) { + filteredList.add(li); + } else { + for(Locale l: appSupportedLocales) { + if(LocaleList.matchesLanguageAndScript(li.getLocale(), l)) { + filteredList.add(li); + break; + } + } + } + } + return filteredList; + } +} diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java index 965895f08d6e..3efd279c2639 100644 --- a/core/java/com/android/internal/app/LocalePickerWithRegion.java +++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java @@ -16,16 +16,12 @@ package com.android.internal.app; -import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus; - import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.ListFragment; import android.content.Context; import android.os.Bundle; -import android.os.LocaleList; import android.text.TextUtils; -import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -36,7 +32,6 @@ import android.widget.SearchView; import com.android.internal.R; -import java.util.Collections; import java.util.HashSet; import java.util.Locale; import java.util.Set; @@ -54,6 +49,7 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O private SuggestedLocaleAdapter mAdapter; private LocaleSelectedListener mListener; + private LocaleCollectorBase mLocalePickerCollector; private Set<LocaleStore.LocaleInfo> mLocaleList; private LocaleStore.LocaleInfo mParentLocale; private boolean mTranslatedOnly = false; @@ -62,7 +58,6 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O private boolean mPreviousSearchHadFocus = false; private int mFirstVisiblePosition = 0; private int mTopDistance = 0; - private String mAppPackageName; private CharSequence mTitle = null; private OnActionExpandListener mOnActionExpandListener; @@ -79,31 +74,50 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O void onLocaleSelected(LocaleStore.LocaleInfo locale); } - private static LocalePickerWithRegion createCountryPicker(Context context, + /** + * The interface which provides the locale list. + */ + interface LocaleCollectorBase { + /** Gets the ignored locale list. */ + HashSet<String> getIgnoredLocaleList(boolean translatedOnly); + + /** Gets the supported locale list. */ + Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, + boolean translatedOnly, boolean isForCountryMode); + + /** Indicates if the class work for specific package. */ + boolean hasSpecificPackageName(); + } + + private static LocalePickerWithRegion createCountryPicker( LocaleSelectedListener listener, LocaleStore.LocaleInfo parent, - boolean translatedOnly, String appPackageName, - OnActionExpandListener onActionExpandListener) { + boolean translatedOnly, OnActionExpandListener onActionExpandListener, + LocaleCollectorBase localePickerCollector) { LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); localePicker.setOnActionExpandListener(onActionExpandListener); - boolean shouldShowTheList = localePicker.setListener(context, listener, parent, - translatedOnly, appPackageName); + boolean shouldShowTheList = localePicker.setListener(listener, parent, + translatedOnly, localePickerCollector); return shouldShowTheList ? localePicker : null; } public static LocalePickerWithRegion createLanguagePicker(Context context, LocaleSelectedListener listener, boolean translatedOnly) { - LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); - localePicker.setListener(context, listener, /* parent */ null, translatedOnly, null); - return localePicker; + return createLanguagePicker(context, listener, translatedOnly, null, null); } public static LocalePickerWithRegion createLanguagePicker(Context context, LocaleSelectedListener listener, boolean translatedOnly, String appPackageName, OnActionExpandListener onActionExpandListener) { + LocaleCollectorBase localePickerController; + if (TextUtils.isEmpty(appPackageName)) { + localePickerController = new SystemLocaleCollector(context); + } else { + localePickerController = new AppLocaleCollector(context, appPackageName); + } LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); localePicker.setOnActionExpandListener(onActionExpandListener); - localePicker.setListener( - context, listener, /* parent */ null, translatedOnly, appPackageName); + localePicker.setListener(listener, /* parent */ null, translatedOnly, + localePickerController); return localePicker; } @@ -120,109 +134,23 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O * In this case we don't even show the list, we call the listener with that locale, * "pretending" it was selected, and return false.</p> */ - private boolean setListener(Context context, LocaleSelectedListener listener, - LocaleStore.LocaleInfo parent, boolean translatedOnly, String appPackageName) { + private boolean setListener(LocaleSelectedListener listener, LocaleStore.LocaleInfo parent, + boolean translatedOnly, LocaleCollectorBase localePickerController) { this.mParentLocale = parent; this.mListener = listener; this.mTranslatedOnly = translatedOnly; - this.mAppPackageName = appPackageName; + this.mLocalePickerCollector = localePickerController; setRetainInstance(true); - final HashSet<String> langTagsToIgnore = new HashSet<>(); - LocaleStore.LocaleInfo appCurrentLocale = - LocaleStore.getAppCurrentLocaleInfo(context, appPackageName); - boolean isForCountryMode = parent != null; - - if (!TextUtils.isEmpty(appPackageName) && !isForCountryMode) { - // Filter current system locale to add them into suggestion - LocaleList systemLangList = LocaleList.getDefault(); - for(int i = 0; i < systemLangList.size(); i++) { - langTagsToIgnore.add(systemLangList.get(i).toLanguageTag()); - } - - if (appCurrentLocale != null) { - Log.d(TAG, "appCurrentLocale: " + appCurrentLocale.getLocale().toLanguageTag()); - langTagsToIgnore.add(appCurrentLocale.getLocale().toLanguageTag()); - } else { - Log.d(TAG, "appCurrentLocale is null"); - } - } else if (!translatedOnly) { - final LocaleList userLocales = LocalePicker.getLocales(); - final String[] langTags = userLocales.toLanguageTags().split(","); - Collections.addAll(langTagsToIgnore, langTags); - } + mLocaleList = localePickerController.getSupportedLocaleList( + parent, translatedOnly, parent != null); - if (isForCountryMode) { - mLocaleList = LocaleStore.getLevelLocales(context, - langTagsToIgnore, parent, translatedOnly); - if (mLocaleList.size() <= 1) { - if (listener != null && (mLocaleList.size() == 1)) { - listener.onLocaleSelected(mLocaleList.iterator().next()); - } - return false; - } + if (parent != null && listener != null && mLocaleList.size() == 1) { + listener.onLocaleSelected(mLocaleList.iterator().next()); + return false; } else { - mLocaleList = LocaleStore.getLevelLocales(context, langTagsToIgnore, - null /* no parent */, translatedOnly); + return true; } - Log.d(TAG, "mLocaleList size: " + mLocaleList.size()); - - // Adding current locale and system default option into suggestion list - if(!TextUtils.isEmpty(appPackageName)) { - if (appCurrentLocale != null && !isForCountryMode) { - mLocaleList.add(appCurrentLocale); - } - - AppLocaleStore.AppLocaleResult result = - AppLocaleStore.getAppSupportedLocales(context, appPackageName); - boolean shouldShowList = - result.mLocaleStatus == LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG - || result.mLocaleStatus == LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_ASSET; - - // Add current system language into suggestion list - for(LocaleStore.LocaleInfo localeInfo: LocaleStore.getSystemCurrentLocaleInfo()) { - boolean isNotCurrentLocale = appCurrentLocale == null - || !localeInfo.getLocale().equals(appCurrentLocale.getLocale()); - if (!isForCountryMode && isNotCurrentLocale) { - mLocaleList.add(localeInfo); - } - } - - // Filter the language not support in app - mLocaleList = filterTheLanguagesNotSupportedInApp( - shouldShowList, result.mAppSupportedLocales); - - Log.d(TAG, "mLocaleList after app-supported filter: " + mLocaleList.size()); - - // Add "system language" - if (!isForCountryMode && shouldShowList) { - mLocaleList.add(LocaleStore.getSystemDefaultLocaleInfo(appCurrentLocale == null)); - } - } - return true; - } - - private Set<LocaleStore.LocaleInfo> filterTheLanguagesNotSupportedInApp( - boolean shouldShowList, HashSet<Locale> supportedLocales) { - Set<LocaleStore.LocaleInfo> filteredList = new HashSet<>(); - if (!shouldShowList) { - return filteredList; - } - - for(LocaleStore.LocaleInfo li: mLocaleList) { - if (supportedLocales.contains(li.getLocale())) { - filteredList.add(li); - } else { - for(Locale l: supportedLocales) { - if(LocaleList.matchesLanguageAndScript(li.getLocale(), l)) { - filteredList.add(li); - break; - } - } - } - } - - return filteredList; } private void returnToParentFrame() { @@ -246,7 +174,9 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O mTitle = getActivity().getTitle(); final boolean countryMode = mParentLocale != null; final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault(); - mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode, mAppPackageName); + final boolean hasSpecificPackageName = + mLocalePickerCollector != null && mLocalePickerCollector.hasSpecificPackageName(); + mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode, hasSpecificPackageName); final LocaleHelper.LocaleInfoComparator comp = new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode); mAdapter.sort(comp); @@ -321,8 +251,8 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O returnToParentFrame(); } else { LocalePickerWithRegion selector = LocalePickerWithRegion.createCountryPicker( - getContext(), mListener, locale, mTranslatedOnly /* translate only */, - mAppPackageName, mOnActionExpandListener); + mListener, locale, mTranslatedOnly /* translate only */, + mOnActionExpandListener, this.mLocalePickerCollector); if (selector != null) { getFragmentManager().beginTransaction() .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) @@ -340,7 +270,8 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O inflater.inflate(R.menu.language_selection_list, menu); final MenuItem searchMenuItem = menu.findItem(R.id.locale_search_menu); - if (!TextUtils.isEmpty(mAppPackageName) && mOnActionExpandListener != null) { + if (mLocalePickerCollector.hasSpecificPackageName() + && mOnActionExpandListener != null) { searchMenuItem.setOnActionExpandListener(mOnActionExpandListener); } diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java index 1be1247b7cc0..5ed0e8bc7883 100644 --- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java +++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java @@ -70,17 +70,17 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { private Locale mDisplayLocale = null; // used to potentially cache a modified Context that uses mDisplayLocale private Context mContextOverride = null; - private String mAppPackageName; + private boolean mHasSpecificAppPackageName; public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) { - this(localeOptions, countryMode, null); + this(localeOptions, countryMode, false); } public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode, - String appPackageName) { + boolean hasSpecificAppPackageName) { mCountryMode = countryMode; mLocaleOptions = new ArrayList<>(localeOptions.size()); - mAppPackageName = appPackageName; + mHasSpecificAppPackageName = hasSpecificAppPackageName; for (LocaleStore.LocaleInfo li : localeOptions) { if (li.isSuggested()) { @@ -134,7 +134,7 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { @Override public int getViewTypeCount() { - if (!TextUtils.isEmpty(mAppPackageName) && showHeaders()) { + if (mHasSpecificAppPackageName && showHeaders()) { // Two headers, 1 "System language", 1 current locale return APP_LANGUAGE_PICKER_TYPE_COUNT; } else if (showHeaders()) { diff --git a/core/java/com/android/internal/app/SystemLocaleCollector.java b/core/java/com/android/internal/app/SystemLocaleCollector.java new file mode 100644 index 000000000000..9a6d4c192fdc --- /dev/null +++ b/core/java/com/android/internal/app/SystemLocaleCollector.java @@ -0,0 +1,66 @@ +/* + * 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.internal.app; + +import android.content.Context; +import android.os.LocaleList; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** The Locale data collector for System language. */ +class SystemLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase { + private final Context mContext; + + SystemLocaleCollector(Context context) { + mContext = context; + } + + @Override + public HashSet<String> getIgnoredLocaleList(boolean translatedOnly) { + HashSet<String> ignoreList = new HashSet<>(); + if (!translatedOnly) { + final LocaleList userLocales = LocalePicker.getLocales(); + final String[] langTags = userLocales.toLanguageTags().split(","); + Collections.addAll(ignoreList, langTags); + } + return ignoreList; + } + + @Override + public Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, + boolean translatedOnly, boolean isForCountryMode) { + Set<String> langTagsToIgnore = getIgnoredLocaleList(translatedOnly); + Set<LocaleStore.LocaleInfo> localeList; + + if (isForCountryMode) { + localeList = LocaleStore.getLevelLocales(mContext, + langTagsToIgnore, parent, translatedOnly); + } else { + localeList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, + null /* no parent */, translatedOnly); + } + return localeList; + } + + + @Override + public boolean hasSpecificPackageName() { + return false; + } +}
\ No newline at end of file diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl index 2d68cb472fa3..51b56dbf582b 100644 --- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl @@ -45,6 +45,7 @@ interface IAppWidgetService { @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) RemoteViews getAppWidgetViews(String callingPackage, int appWidgetId); int[] getAppWidgetIdsForHost(String callingPackage, int hostId); + void setAppWidgetHidden(in String callingPackage, int hostId); IntentSender createAppWidgetConfigIntentSender(String callingPackage, int appWidgetId, int intentFlags); diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 44cfe1aa4a79..1d4b246de5c8 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -322,4 +322,7 @@ oneway interface IStatusBar /** Unregisters a nearby media devices provider. */ void unregisterNearbyMediaDevicesProvider(in INearbyMediaDevicesProvider provider); + + /** Dump protos from SystemUI. The proto definition is defined there */ + void dumpProto(in String[] args, in ParcelFileDescriptor pfd); } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 964fe2d57b0d..f7467b5a9f86 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1147,7 +1147,28 @@ android:protectionLevel="dangerous" /> <!-- Allows an application to write to external storage. - <p class="note"><strong>Note:</strong> If <em>both</em> your <a + <p><strong>Note: </strong>If your app targets {@link android.os.Build.VERSION_CODES#R} or + higher, this permission has no effect. + + <p>If your app is on a device that runs API level 19 or higher, you don't need to declare + this permission to read and write files in your application-specific directories returned + by {@link android.content.Context#getExternalFilesDir} and + {@link android.content.Context#getExternalCacheDir}. + + <p>Learn more about how to + <a href="{@docRoot}training/data-storage/shared/media#update-other-apps-files">modify media + files</a> that your app doesn't own, and how to + <a href="{@docRoot}training/data-storage/shared/documents-files">modify non-media files</a> + that your app doesn't own. + + <p>If your app is a file manager and needs broad access to external storage files, then + the system must place your app on an allowlist so that you can successfully request the + <a href="#MANAGE_EXTERNAL_STORAGE><code>MANAGE_EXTERNAL_STORAGE</code></a> permission. + Learn more about the appropriate use cases for + <a href="{@docRoot}training/data-storage/manage-all-files>managing all files on a storage + device</a>. + + <p>If <em>both</em> your <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> and <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code @@ -1155,12 +1176,6 @@ grants your app this permission. If you don't need this permission, be sure your <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> is 4 or higher. - <p>Starting in API level 19, this permission is <em>not</em> required to - read/write files in your application-specific directories returned by - {@link android.content.Context#getExternalFilesDir} and - {@link android.content.Context#getExternalCacheDir}. - <p>If this permission is not allowlisted for an app that targets an API level before - {@link android.os.Build.VERSION_CODES#Q} this permission cannot be granted to apps.</p> <p>Protection level: dangerous</p> --> <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 2a3f916dcdec..e8e5a514d15f 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1970,8 +1970,8 @@ <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Presiona para ver archivos"</string> <string name="pin_target" msgid="8036028973110156895">"Fijar"</string> <string name="pin_specific_target" msgid="7824671240625957415">"Fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string> - <string name="unpin_target" msgid="3963318576590204447">"No fijar"</string> - <string name="unpin_specific_target" msgid="3859828252160908146">"No fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string> + <string name="unpin_target" msgid="3963318576590204447">"Dejar de fijar"</string> + <string name="unpin_specific_target" msgid="3859828252160908146">"Dejar de fijar <xliff:g id="LABEL">%1$s</xliff:g>"</string> <string name="app_info" msgid="6113278084877079851">"Información de apps"</string> <string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="demo_starting_message" msgid="6577581216125805905">"Iniciando demostración…"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 79faaac94919..0daa3249cc0c 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1139,7 +1139,7 @@ <string name="copy" msgid="5472512047143665218">"कॉपी करें"</string> <string name="failed_to_copy_to_clipboard" msgid="725919885138539875">"क्लिपबोर्ड पर कॉपी नहीं हो सका"</string> <string name="paste" msgid="461843306215520225">"चिपकाएं"</string> - <string name="paste_as_plain_text" msgid="7664800665823182587">"सादे पाठ के रूप में चिपकाएं"</string> + <string name="paste_as_plain_text" msgid="7664800665823182587">"सादे टेक्स्ट के रूप में चिपकाएं"</string> <string name="replace" msgid="7842675434546657444">"बदलें•"</string> <string name="delete" msgid="1514113991712129054">"मिटाएं"</string> <string name="copyUrl" msgid="6229645005987260230">"यूआरएल को कॉपी करें"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 9ab64e6f26df..d11eca61752f 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -252,7 +252,7 @@ <string name="bugreport_message" msgid="5212529146119624326">"현재 기기 상태에 대한 정보를 수집하여 이메일 메시지로 전송합니다. 버그 신고를 시작하여 전송할 준비가 되려면 약간 시간이 걸립니다."</string> <string name="bugreport_option_interactive_title" msgid="7968287837902871289">"대화형 보고서"</string> <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"대부분의 경우 이 옵션을 사용합니다. 신고 진행 상황을 추적하고 문제에 대한 세부정보를 입력하고 스크린샷을 찍을 수 있습니다. 신고하기에 시간이 너무 오래 걸리고 사용 빈도가 낮은 일부 섹션을 생략할 수 있습니다."</string> - <string name="bugreport_option_full_title" msgid="7681035745950045690">"전체 보고서"</string> + <string name="bugreport_option_full_title" msgid="7681035745950045690">"전체 신고"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"기기가 응답하지 않거나 너무 느리거나 모든 보고서 섹션이 필요한 경우 이 옵션을 사용하여 시스템 방해를 최소화합니다. 세부정보를 추가하거나 스크린샷을 추가로 찍을 수 없습니다."</string> <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{버그 신고 스크린샷을 #초 후에 찍습니다.}other{버그 신고 스크린샷을 #초 후에 찍습니다.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"버그 신고용 스크린샷 촬영 완료"</string> diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java index 0b8b29b9dda9..bcb13d2108b8 100644 --- a/core/tests/coretests/src/android/app/NotificationTest.java +++ b/core/tests/coretests/src/android/app/NotificationTest.java @@ -48,6 +48,7 @@ import static com.android.internal.util.ContrastColorUtilTest.assertContrastIsWi import static com.google.common.truth.Truth.assertThat; +import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.fail; import static org.junit.Assert.assertEquals; @@ -56,7 +57,9 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.app.Notification.CallStyle; @@ -68,6 +71,7 @@ import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; +import android.graphics.Typeface; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Build; @@ -79,7 +83,9 @@ import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ForegroundColorSpan; +import android.text.style.StyleSpan; import android.text.style.TextAppearanceSpan; +import android.util.Pair; import android.widget.RemoteViews; import androidx.test.InstrumentationRegistry; @@ -89,6 +95,8 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; import com.android.internal.util.ContrastColorUtil; +import junit.framework.Assert; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -218,8 +226,10 @@ public class NotificationTest { @Test public void allPendingIntents_recollectedAfterReusingBuilder() { - PendingIntent intent1 = PendingIntent.getActivity(mContext, 0, new Intent("test1"), PendingIntent.FLAG_MUTABLE_UNAUDITED); - PendingIntent intent2 = PendingIntent.getActivity(mContext, 0, new Intent("test2"), PendingIntent.FLAG_MUTABLE_UNAUDITED); + PendingIntent intent1 = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); + PendingIntent intent2 = PendingIntent.getActivity( + mContext, 0, new Intent("test2"), PendingIntent.FLAG_IMMUTABLE); Notification.Builder builder = new Notification.Builder(mContext, "channel"); builder.setContentIntent(intent1); @@ -669,30 +679,23 @@ public class NotificationTest { Notification notification = new Notification.Builder(mContext, "Channel").setStyle( style).build(); + int targetSize = mContext.getResources().getDimensionPixelSize( + ActivityManager.isLowRamDeviceStatic() + ? R.dimen.notification_person_icon_max_size_low_ram + : R.dimen.notification_person_icon_max_size); + Bitmap personIcon = style.getUser().getIcon().getBitmap(); - assertThat(personIcon.getWidth()).isEqualTo( - mContext.getResources().getDimensionPixelSize( - R.dimen.notification_person_icon_max_size)); - assertThat(personIcon.getHeight()).isEqualTo( - mContext.getResources().getDimensionPixelSize( - R.dimen.notification_person_icon_max_size)); + assertThat(personIcon.getWidth()).isEqualTo(targetSize); + assertThat(personIcon.getHeight()).isEqualTo(targetSize); Bitmap avatarIcon = style.getMessages().get(0).getSenderPerson().getIcon().getBitmap(); - assertThat(avatarIcon.getWidth()).isEqualTo( - mContext.getResources().getDimensionPixelSize( - R.dimen.notification_person_icon_max_size)); - assertThat(avatarIcon.getHeight()).isEqualTo( - mContext.getResources().getDimensionPixelSize( - R.dimen.notification_person_icon_max_size)); + assertThat(avatarIcon.getWidth()).isEqualTo(targetSize); + assertThat(avatarIcon.getHeight()).isEqualTo(targetSize); Bitmap historicAvatarIcon = style.getHistoricMessages().get( 0).getSenderPerson().getIcon().getBitmap(); - assertThat(historicAvatarIcon.getWidth()).isEqualTo( - mContext.getResources().getDimensionPixelSize( - R.dimen.notification_person_icon_max_size)); - assertThat(historicAvatarIcon.getHeight()).isEqualTo( - mContext.getResources().getDimensionPixelSize( - R.dimen.notification_person_icon_max_size)); + assertThat(historicAvatarIcon.getWidth()).isEqualTo(targetSize); + assertThat(historicAvatarIcon.getHeight()).isEqualTo(targetSize); } @Test @@ -780,7 +783,6 @@ public class NotificationTest { assertFalse(notification.isMediaNotification()); } - @Test public void validateColorizedPaletteForColor(int rawColor) { Notification.Colors cDay = new Notification.Colors(); Notification.Colors cNight = new Notification.Colors(); @@ -861,19 +863,22 @@ public class NotificationTest { Bundle fakeTypes = new Bundle(); fakeTypes.putParcelable(EXTRA_LARGE_ICON_BIG, new Bundle()); - style.restoreFromExtras(fakeTypes); // no crash, good } @Test public void testRestoreFromExtras_Messaging_invalidExtra_noCrash() { - Notification.Style style = new Notification.MessagingStyle(); + Notification.Style style = new Notification.MessagingStyle("test"); Bundle fakeTypes = new Bundle(); fakeTypes.putParcelable(EXTRA_MESSAGING_PERSON, new Bundle()); fakeTypes.putParcelable(EXTRA_CONVERSATION_ICON, new Bundle()); - style.restoreFromExtras(fakeTypes); + Notification n = new Notification.Builder(mContext, "test") + .setStyle(style) + .setExtras(fakeTypes) + .build(); + Notification.Builder.recoverBuilder(mContext, n); // no crash, good } @@ -885,22 +890,33 @@ public class NotificationTest { fakeTypes.putParcelable(EXTRA_MEDIA_SESSION, new Bundle()); fakeTypes.putParcelable(EXTRA_MEDIA_REMOTE_INTENT, new Bundle()); - style.restoreFromExtras(fakeTypes); + Notification n = new Notification.Builder(mContext, "test") + .setStyle(style) + .setExtras(fakeTypes) + .build(); + Notification.Builder.recoverBuilder(mContext, n); // no crash, good } @Test public void testRestoreFromExtras_Call_invalidExtra_noCrash() { - Notification.Style style = new CallStyle(); + PendingIntent intent1 = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); + Notification.Style style = Notification.CallStyle.forIncomingCall( + new Person.Builder().setName("hi").build(), intent1, intent1); + Bundle fakeTypes = new Bundle(); fakeTypes.putParcelable(EXTRA_CALL_PERSON, new Bundle()); fakeTypes.putParcelable(EXTRA_ANSWER_INTENT, new Bundle()); fakeTypes.putParcelable(EXTRA_DECLINE_INTENT, new Bundle()); fakeTypes.putParcelable(EXTRA_HANG_UP_INTENT, new Bundle()); - style.restoreFromExtras(fakeTypes); - + Notification n = new Notification.Builder(mContext, "test") + .setStyle(style) + .setExtras(fakeTypes) + .build(); + Notification.Builder.recoverBuilder(mContext, n); // no crash, good } @@ -962,7 +978,11 @@ public class NotificationTest { fakeTypes.putParcelable(KEY_ON_READ, new Bundle()); fakeTypes.putParcelable(KEY_ON_REPLY, new Bundle()); fakeTypes.putParcelable(KEY_REMOTE_INPUT, new Bundle()); - Notification.CarExtender.UnreadConversation.getUnreadConversationFromBundle(fakeTypes); + + Notification n = new Notification.Builder(mContext, "test") + .setExtras(fakeTypes) + .build(); + Notification.CarExtender extender = new Notification.CarExtender(n); // no crash, good } @@ -980,6 +1000,493 @@ public class NotificationTest { // no crash, good } + + @Test + public void testDoesNotStripsExtenders() { + Notification.Builder nb = new Notification.Builder(mContext, "channel"); + nb.extend(new Notification.CarExtender().setColor(Color.RED)); + nb.extend(new Notification.TvExtender().setChannelId("different channel")); + nb.extend(new Notification.WearableExtender().setDismissalId("dismiss")); + Notification before = nb.build(); + Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before); + + assertTrue(before == after); + + Assert.assertEquals("different channel", + new Notification.TvExtender(before).getChannelId()); + Assert.assertEquals(Color.RED, new Notification.CarExtender(before).getColor()); + Assert.assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId()); + } + + @Test + public void testStyleChangeVisiblyDifferent_noStyles() { + Notification.Builder n1 = new Notification.Builder(mContext, "test"); + Notification.Builder n2 = new Notification.Builder(mContext, "test"); + + assertFalse(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); + } + + @Test + public void testStyleChangeVisiblyDifferent_noStyleToStyle() { + Notification.Builder n1 = new Notification.Builder(mContext, "test"); + Notification.Builder n2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.BigTextStyle()); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); + } + + @Test + public void testStyleChangeVisiblyDifferent_styleToNoStyle() { + Notification.Builder n2 = new Notification.Builder(mContext, "test"); + Notification.Builder n1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.BigTextStyle()); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); + } + + @Test + public void testStyleChangeVisiblyDifferent_changeStyle() { + Notification.Builder n1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.InboxStyle()); + Notification.Builder n2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.BigTextStyle()); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); + } + + @Test + public void testInboxTextChange() { + Notification.Builder nInbox1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.InboxStyle().addLine("a").addLine("b")); + Notification.Builder nInbox2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.InboxStyle().addLine("b").addLine("c")); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nInbox1, nInbox2)); + } + + @Test + public void testBigTextTextChange() { + Notification.Builder nBigText1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.BigTextStyle().bigText("something")); + Notification.Builder nBigText2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.BigTextStyle().bigText("else")); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nBigText1, nBigText2)); + } + + @Test + public void testBigPictureChange() { + Bitmap bitA = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888); + Bitmap bitB = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888); + + Notification.Builder nBigPic1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.BigPictureStyle().bigPicture(bitA)); + Notification.Builder nBigPic2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.BigPictureStyle().bigPicture(bitB)); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nBigPic1, nBigPic2)); + } + + @Test + public void testMessagingChange_text() { + Notification.Builder nM1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message( + "a", 100, new Person.Builder().setName("hi").build()))); + Notification.Builder nM2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message( + "a", 100, new Person.Builder().setName("hi").build())) + .addMessage(new Notification.MessagingStyle.Message( + "b", 100, new Person.Builder().setName("hi").build())) + ); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); + } + + @Test + public void testMessagingChange_data() { + Notification.Builder nM1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message( + "a", 100, new Person.Builder().setName("hi").build()) + .setData("text", mock(Uri.class)))); + Notification.Builder nM2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message( + "a", 100, new Person.Builder().setName("hi").build()))); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); + } + + @Test + public void testMessagingChange_sender() { + Person a = new Person.Builder().setName("A").build(); + Person b = new Person.Builder().setName("b").build(); + Notification.Builder nM1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message("a", 100, b))); + Notification.Builder nM2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message("a", 100, a))); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); + } + + @Test + public void testMessagingChange_key() { + Person a = new Person.Builder().setName("hi").setKey("A").build(); + Person b = new Person.Builder().setName("hi").setKey("b").build(); + Notification.Builder nM1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message("a", 100, a))); + Notification.Builder nM2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message("a", 100, b))); + + assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); + } + + @Test + public void testMessagingChange_ignoreTimeChange() { + Notification.Builder nM1 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message( + "a", 100, new Person.Builder().setName("hi").build()))); + Notification.Builder nM2 = new Notification.Builder(mContext, "test") + .setStyle(new Notification.MessagingStyle("") + .addMessage(new Notification.MessagingStyle.Message( + "a", 1000, new Person.Builder().setName("hi").build())) + ); + + assertFalse(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); + } + + @Test + public void testRemoteViews_nullChange() { + Notification.Builder n1 = new Notification.Builder(mContext, "test") + .setContent(mock(RemoteViews.class)); + Notification.Builder n2 = new Notification.Builder(mContext, "test"); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test"); + n2 = new Notification.Builder(mContext, "test") + .setContent(mock(RemoteViews.class)); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test") + .setCustomBigContentView(mock(RemoteViews.class)); + n2 = new Notification.Builder(mContext, "test"); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test"); + n2 = new Notification.Builder(mContext, "test") + .setCustomBigContentView(mock(RemoteViews.class)); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test"); + n2 = new Notification.Builder(mContext, "test"); + assertFalse(Notification.areRemoteViewsChanged(n1, n2)); + } + + @Test + public void testRemoteViews_layoutChange() { + RemoteViews a = mock(RemoteViews.class); + when(a.getLayoutId()).thenReturn(234); + RemoteViews b = mock(RemoteViews.class); + when(b.getLayoutId()).thenReturn(189); + + Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); + Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); + n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); + n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + } + + @Test + public void testRemoteViews_layoutSame() { + RemoteViews a = mock(RemoteViews.class); + when(a.getLayoutId()).thenReturn(234); + RemoteViews b = mock(RemoteViews.class); + when(b.getLayoutId()).thenReturn(234); + + Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); + Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); + assertFalse(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); + n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); + assertFalse(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); + n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); + assertFalse(Notification.areRemoteViewsChanged(n1, n2)); + } + + @Test + public void testRemoteViews_sequenceChange() { + RemoteViews a = mock(RemoteViews.class); + when(a.getLayoutId()).thenReturn(234); + when(a.getSequenceNumber()).thenReturn(1); + RemoteViews b = mock(RemoteViews.class); + when(b.getLayoutId()).thenReturn(234); + when(b.getSequenceNumber()).thenReturn(2); + + Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); + Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); + n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); + n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); + assertTrue(Notification.areRemoteViewsChanged(n1, n2)); + } + + @Test + public void testRemoteViews_sequenceSame() { + RemoteViews a = mock(RemoteViews.class); + when(a.getLayoutId()).thenReturn(234); + when(a.getSequenceNumber()).thenReturn(1); + RemoteViews b = mock(RemoteViews.class); + when(b.getLayoutId()).thenReturn(234); + when(b.getSequenceNumber()).thenReturn(1); + + Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); + Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); + assertFalse(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); + n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); + assertFalse(Notification.areRemoteViewsChanged(n1, n2)); + + n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); + n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); + assertFalse(Notification.areRemoteViewsChanged(n1, n2)); + } + + @Test + public void testActionsDifferent_null() { + Notification n1 = new Notification.Builder(mContext, "test") + .build(); + Notification n2 = new Notification.Builder(mContext, "test") + .build(); + + assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); + } + + @Test + public void testActionsDifferentSame() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + + Notification n1 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) + .build(); + Notification n2 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) + .build(); + + assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); + } + + @Test + public void testActionsDifferentText() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + + Notification n1 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) + .build(); + Notification n2 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 2", intent).build()) + .build(); + + assertTrue(Notification.areActionsVisiblyDifferent(n1, n2)); + } + + @Test + public void testActionsDifferentSpannables() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + + Notification n1 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, + new SpannableStringBuilder().append("test1", + new StyleSpan(Typeface.BOLD), + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE), + intent).build()) + .build(); + Notification n2 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "test1", intent).build()) + .build(); + + assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); + } + + @Test + public void testActionsDifferentNumber() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + + Notification n1 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) + .build(); + Notification n2 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) + .addAction(new Notification.Action.Builder(icon, "TEXT 2", intent).build()) + .build(); + + assertTrue(Notification.areActionsVisiblyDifferent(n1, n2)); + } + + @Test + public void testActionsDifferentIntent() { + PendingIntent intent1 = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); + PendingIntent intent2 = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE); + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + + Notification n1 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent1).build()) + .build(); + Notification n2 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent2).build()) + .build(); + + assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); + } + + @Test + public void testActionsIgnoresRemoteInputs() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + + Notification n1 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) + .addRemoteInput(new RemoteInput.Builder("a") + .setChoices(new CharSequence[] {"i", "m"}) + .build()) + .build()) + .build(); + Notification n2 = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) + .addRemoteInput(new RemoteInput.Builder("a") + .setChoices(new CharSequence[] {"t", "m"}) + .build()) + .build()) + .build(); + + assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); + } + + @Test + public void testFreeformRemoteInputActionPair_noRemoteInput() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + Notification notification = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) + .build()) + .build(); + Assert.assertNull(notification.findRemoteInputActionPair(false)); + } + + @Test + public void testFreeformRemoteInputActionPair_hasRemoteInput() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + + RemoteInput remoteInput = new RemoteInput.Builder("a").build(); + + Notification.Action actionWithRemoteInput = + new Notification.Action.Builder(icon, "TEXT 1", intent) + .addRemoteInput(remoteInput) + .addRemoteInput(remoteInput) + .build(); + + Notification.Action actionWithoutRemoteInput = + new Notification.Action.Builder(icon, "TEXT 2", intent) + .build(); + + Notification notification = new Notification.Builder(mContext, "test") + .addAction(actionWithoutRemoteInput) + .addAction(actionWithRemoteInput) + .build(); + + Pair<RemoteInput, Notification.Action> remoteInputActionPair = + notification.findRemoteInputActionPair(false); + + assertNotNull(remoteInputActionPair); + Assert.assertEquals(remoteInput, remoteInputActionPair.first); + Assert.assertEquals(actionWithRemoteInput, remoteInputActionPair.second); + } + + @Test + public void testFreeformRemoteInputActionPair_requestFreeform_noFreeformRemoteInput() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + Notification notification = new Notification.Builder(mContext, "test") + .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) + .addRemoteInput( + new RemoteInput.Builder("a") + .setAllowFreeFormInput(false).build()) + .build()) + .build(); + Assert.assertNull(notification.findRemoteInputActionPair(true)); + } + + @Test + public void testFreeformRemoteInputActionPair_requestFreeform_hasFreeformRemoteInput() { + PendingIntent intent = PendingIntent.getActivity( + mContext, 0, new Intent("test1"), PendingIntent.FLAG_IMMUTABLE);; + Icon icon = Icon.createWithBitmap(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888)); + + RemoteInput remoteInput = + new RemoteInput.Builder("a").setAllowFreeFormInput(false).build(); + RemoteInput freeformRemoteInput = + new RemoteInput.Builder("b").setAllowFreeFormInput(true).build(); + + Notification.Action actionWithFreeformRemoteInput = + new Notification.Action.Builder(icon, "TEXT 1", intent) + .addRemoteInput(remoteInput) + .addRemoteInput(freeformRemoteInput) + .build(); + + Notification.Action actionWithoutFreeformRemoteInput = + new Notification.Action.Builder(icon, "TEXT 2", intent) + .addRemoteInput(remoteInput) + .build(); + + Notification notification = new Notification.Builder(mContext, "test") + .addAction(actionWithoutFreeformRemoteInput) + .addAction(actionWithFreeformRemoteInput) + .build(); + + Pair<RemoteInput, Notification.Action> remoteInputActionPair = + notification.findRemoteInputActionPair(true); + + assertNotNull(remoteInputActionPair); + Assert.assertEquals(freeformRemoteInput, remoteInputActionPair.first); + Assert.assertEquals(actionWithFreeformRemoteInput, remoteInputActionPair.second); + } + private void assertValid(Notification.Colors c) { // Assert that all colors are populated assertThat(c.getBackgroundColor()).isNotEqualTo(Notification.COLOR_INVALID); diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index 0fdfed86b29e..17b1d1bdbff1 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"አስፋ"</string> <string name="minimize_button_text" msgid="271592547935841753">"አሳንስ"</string> <string name="close_button_text" msgid="2913281996024033299">"ዝጋ"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"ተመለስ"</string> + <string name="handle_text" msgid="1766582106752184456">"መያዣ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index 351e1928a260..2babc3ea5fcd 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"تكبير"</string> <string name="minimize_button_text" msgid="271592547935841753">"تصغير"</string> <string name="close_button_text" msgid="2913281996024033299">"إغلاق"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"رجوع"</string> + <string name="handle_text" msgid="1766582106752184456">"مقبض"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index 765aaba4d23c..fe43cd69110f 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"সৰ্বাধিক মাত্ৰালৈ বঢ়াওক"</string> <string name="minimize_button_text" msgid="271592547935841753">"মিনিমাইজ কৰক"</string> <string name="close_button_text" msgid="2913281996024033299">"বন্ধ কৰক"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"উভতি যাওক"</string> + <string name="handle_text" msgid="1766582106752184456">"হেণ্ডেল"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index 0ec5db185e34..c22f5425048e 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Böyüdün"</string> <string name="minimize_button_text" msgid="271592547935841753">"Kiçildin"</string> <string name="close_button_text" msgid="2913281996024033299">"Bağlayın"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Geriyə"</string> + <string name="handle_text" msgid="1766582106752184456">"Hər kəsə açıq istifadəçi adı"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index bd4a079f54c6..cf5394b0ebd2 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Разгарнуць"</string> <string name="minimize_button_text" msgid="271592547935841753">"Згарнуць"</string> <string name="close_button_text" msgid="2913281996024033299">"Закрыць"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> + <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index a04a50da7089..c525f521c0e3 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Увеличаване"</string> <string name="minimize_button_text" msgid="271592547935841753">"Намаляване"</string> <string name="close_button_text" msgid="2913281996024033299">"Затваряне"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> + <string name="handle_text" msgid="1766582106752184456">"Манипулатор"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 2cc0ab321b4a..bec284d4dff8 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -84,6 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziranje"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimiziranje"</string> <string name="close_button_text" msgid="2913281996024033299">"Zatvaranje"</string> - <string name="back_button_text" msgid="1469718707134137085">"Natrag"</string> - <string name="handle_text" msgid="1766582106752184456">"Pokazivač"</string> + <string name="back_button_text" msgid="1469718707134137085">"Nazad"</string> + <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index a2badaf06989..c84bb4884068 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maximitza"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimitza"</string> <string name="close_button_text" msgid="2913281996024033299">"Tanca"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Enrere"</string> + <string name="handle_text" msgid="1766582106752184456">"Ansa"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index 084ea865f769..60c1f8588445 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksimér"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string> <string name="close_button_text" msgid="2913281996024033299">"Luk"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Tilbage"</string> + <string name="handle_text" msgid="1766582106752184456">"Håndtag"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 195c3355df2d..b57f0c857d26 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maximieren"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimieren"</string> <string name="close_button_text" msgid="2913281996024033299">"Schließen"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Zurück"</string> + <string name="handle_text" msgid="1766582106752184456">"Ziehpunkt"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index 0ad387bbd39c..aed03acf026c 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Atrás"</string> + <string name="handle_text" msgid="1766582106752184456">"Controlador"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 4b85a22a12aa..bddc2c3e61bc 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <string name="close_button_text" msgid="2913281996024033299">"Cerrar"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Atrás"</string> + <string name="handle_text" msgid="1766582106752184456">"Controlador"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index cc9057815ca2..696a520d0b86 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksimeeri"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimeeri"</string> <string name="close_button_text" msgid="2913281996024033299">"Sule"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Tagasi"</string> + <string name="handle_text" msgid="1766582106752184456">"Käepide"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index a1d0b5851f84..7550a091bd79 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"بزرگ کردن"</string> <string name="minimize_button_text" msgid="271592547935841753">"کوچک کردن"</string> <string name="close_button_text" msgid="2913281996024033299">"بستن"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"برگشتن"</string> + <string name="handle_text" msgid="1766582106752184456">"دستگیره"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index 5df1e04abb2a..a79adf8e686c 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Suurenna"</string> <string name="minimize_button_text" msgid="271592547935841753">"Pienennä"</string> <string name="close_button_text" msgid="2913281996024033299">"Sulje"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Takaisin"</string> + <string name="handle_text" msgid="1766582106752184456">"Kahva"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index c4b386aad3d1..865e2dcf4775 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string> <string name="minimize_button_text" msgid="271592547935841753">"Réduire"</string> <string name="close_button_text" msgid="2913281996024033299">"Fermer"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Retour"</string> + <string name="handle_text" msgid="1766582106752184456">"Poignée"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index f5a106d3956d..47e6696dfe4c 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimizar"</string> <string name="close_button_text" msgid="2913281996024033299">"Pechar"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Atrás"</string> + <string name="handle_text" msgid="1766582106752184456">"Controlador"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 95484d5fa1d5..2c643ded9dee 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"बड़ा करें"</string> <string name="minimize_button_text" msgid="271592547935841753">"विंडो छोटी करें"</string> <string name="close_button_text" msgid="2913281996024033299">"बंद करें"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"वापस जाएं"</string> + <string name="handle_text" msgid="1766582106752184456">"हैंडल"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index 5ae72eb27df2..d3bca3374e9d 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Ծավալել"</string> <string name="minimize_button_text" msgid="271592547935841753">"Ծալել"</string> <string name="close_button_text" msgid="2913281996024033299">"Փակել"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Հետ"</string> + <string name="handle_text" msgid="1766582106752184456">"Նշիչ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index d36a83f115ec..f157fcf6dbec 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksimalkan"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimalkan"</string> <string name="close_button_text" msgid="2913281996024033299">"Tutup"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Kembali"</string> + <string name="handle_text" msgid="1766582106752184456">"Tuas"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index 31d483ed7c1a..ead1757ed4bb 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Stækka"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minnka"</string> <string name="close_button_text" msgid="2913281996024033299">"Loka"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Til baka"</string> + <string name="handle_text" msgid="1766582106752184456">"Handfang"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 5c9425e92929..12c962d09ce1 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"הגדלה"</string> <string name="minimize_button_text" msgid="271592547935841753">"מזעור"</string> <string name="close_button_text" msgid="2913281996024033299">"סגירה"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"חזרה"</string> + <string name="handle_text" msgid="1766582106752184456">"נקודת אחיזה"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index 787ac3e1af00..b28436131fe9 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"მაქსიმალურად გაშლა"</string> <string name="minimize_button_text" msgid="271592547935841753">"ჩაკეცვა"</string> <string name="close_button_text" msgid="2913281996024033299">"დახურვა"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"უკან"</string> + <string name="handle_text" msgid="1766582106752184456">"იდენტიფიკატორი"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index 927f0d7a0dde..2d842b88996a 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Жаю"</string> <string name="minimize_button_text" msgid="271592547935841753">"Кішірейту"</string> <string name="close_button_text" msgid="2913281996024033299">"Жабу"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Артқа"</string> + <string name="handle_text" msgid="1766582106752184456">"Идентификатор"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index 955b2f88f314..3243a648ac0e 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"ពង្រីក"</string> <string name="minimize_button_text" msgid="271592547935841753">"បង្រួម"</string> <string name="close_button_text" msgid="2913281996024033299">"បិទ"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"ថយក្រោយ"</string> + <string name="handle_text" msgid="1766582106752184456">"ឈ្មោះអ្នកប្រើប្រាស់"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index a69e105876be..3a655b870df3 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"최대화"</string> <string name="minimize_button_text" msgid="271592547935841753">"최소화"</string> <string name="close_button_text" msgid="2913281996024033299">"닫기"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"뒤로"</string> + <string name="handle_text" msgid="1766582106752184456">"핸들"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index 15bde88c7afb..b800e3eb174f 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"ຂະຫຍາຍໃຫຍ່ສຸດ"</string> <string name="minimize_button_text" msgid="271592547935841753">"ຫຍໍ້ລົງ"</string> <string name="close_button_text" msgid="2913281996024033299">"ປິດ"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"ກັບຄືນ"</string> + <string name="handle_text" msgid="1766582106752184456">"ມືບັງຄັບ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index 275efa203a74..94339a46df6f 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Padidinti"</string> <string name="minimize_button_text" msgid="271592547935841753">"Sumažinti"</string> <string name="close_button_text" msgid="2913281996024033299">"Uždaryti"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Atgal"</string> + <string name="handle_text" msgid="1766582106752184456">"Rankenėlė"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index 3048630e2344..d28245360922 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksimizēt"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimizēt"</string> <string name="close_button_text" msgid="2913281996024033299">"Aizvērt"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Atpakaļ"</string> + <string name="handle_text" msgid="1766582106752184456">"Turis"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml index 9013828fb487..5db8d6d071f1 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"വലുതാക്കുക"</string> <string name="minimize_button_text" msgid="271592547935841753">"ചെറുതാക്കുക"</string> <string name="close_button_text" msgid="2913281996024033299">"അടയ്ക്കുക"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"മടങ്ങുക"</string> + <string name="handle_text" msgid="1766582106752184456">"ഹാൻഡിൽ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index dc884e9bf3dd..779cf5c870bc 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"मोठे करा"</string> <string name="minimize_button_text" msgid="271592547935841753">"लहान करा"</string> <string name="close_button_text" msgid="2913281996024033299">"बंद करा"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"मागे जा"</string> + <string name="handle_text" msgid="1766582106752184456">"हँडल"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index a2f24f2c948b..0ceee2d1c928 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksimer"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimer"</string> <string name="close_button_text" msgid="2913281996024033299">"Lukk"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Tilbake"</string> + <string name="handle_text" msgid="1766582106752184456">"Håndtak"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml index 6a70d8da05ed..7ba49e57111e 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"ठुलो बनाउनुहोस्"</string> <string name="minimize_button_text" msgid="271592547935841753">"मिनिमाइज गर्नुहोस्"</string> <string name="close_button_text" msgid="2913281996024033299">"बन्द गर्नुहोस्"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"पछाडि"</string> + <string name="handle_text" msgid="1766582106752184456">"ह्यान्डल"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index d1d7db80caf5..dd3ebe415218 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maximaliseren"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimaliseren"</string> <string name="close_button_text" msgid="2913281996024033299">"Sluiten"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Terug"</string> + <string name="handle_text" msgid="1766582106752184456">"Gebruikersnaam"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index d2a96d95db74..c3056ca0a511 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"ਵੱਡਾ ਕਰੋ"</string> <string name="minimize_button_text" msgid="271592547935841753">"ਛੋਟਾ ਕਰੋ"</string> <string name="close_button_text" msgid="2913281996024033299">"ਬੰਦ ਕਰੋ"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"ਪਿੱਛੇ"</string> + <string name="handle_text" msgid="1766582106752184456">"ਹੈਂਡਲ"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index cc2b2c314a85..56a6fb1664c1 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksymalizuj"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimalizuj"</string> <string name="close_button_text" msgid="2913281996024033299">"Zamknij"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Wstecz"</string> + <string name="handle_text" msgid="1766582106752184456">"Uchwyt"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index 98a775e1e6b3..b96caf23a0a7 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Развернуть"</string> <string name="minimize_button_text" msgid="271592547935841753">"Свернуть"</string> <string name="close_button_text" msgid="2913281996024033299">"Закрыть"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> + <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index 57240618ef19..a1ec3b5d5bb2 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"විහිදන්න"</string> <string name="minimize_button_text" msgid="271592547935841753">"කුඩා කරන්න"</string> <string name="close_button_text" msgid="2913281996024033299">"වසන්න"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"ආපසු"</string> + <string name="handle_text" msgid="1766582106752184456">"හැඬලය"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index 12f022e7a1f6..2f995e5076f3 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiraj"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimiraj"</string> <string name="close_button_text" msgid="2913281996024033299">"Zapri"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Nazaj"</string> + <string name="handle_text" msgid="1766582106752184456">"Ročica"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index cdd870689886..3d9bde4f8066 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Maksimizo"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimizo"</string> <string name="close_button_text" msgid="2913281996024033299">"Mbyll"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Pas"</string> + <string name="handle_text" msgid="1766582106752184456">"Emërtimi"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index fef3792b35a2..b39fd04ebf3d 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Utöka"</string> <string name="minimize_button_text" msgid="271592547935841753">"Minimera"</string> <string name="close_button_text" msgid="2913281996024033299">"Stäng"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Tillbaka"</string> + <string name="handle_text" msgid="1766582106752184456">"Handtag"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index 2d10e2039a11..f4d4ceec5a1f 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Panua"</string> <string name="minimize_button_text" msgid="271592547935841753">"Punguza"</string> <string name="close_button_text" msgid="2913281996024033299">"Funga"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Rudi nyuma"</string> + <string name="handle_text" msgid="1766582106752184456">"Ncha"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index 0eeeca78cb86..6d050c2ba26e 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"பெரிதாக்கும்"</string> <string name="minimize_button_text" msgid="271592547935841753">"சிறிதாக்கும்"</string> <string name="close_button_text" msgid="2913281996024033299">"மூடும்"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"பின்செல்லும்"</string> + <string name="handle_text" msgid="1766582106752184456">"ஹேண்டில்"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index 2b105bdb7963..025e2e6215e7 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Ekranı Kapla"</string> <string name="minimize_button_text" msgid="271592547935841753">"Küçült"</string> <string name="close_button_text" msgid="2913281996024033299">"Kapat"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Geri"</string> + <string name="handle_text" msgid="1766582106752184456">"Herkese açık kullanıcı adı"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index a0925318ac26..97bb68080117 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Збільшити"</string> <string name="minimize_button_text" msgid="271592547935841753">"Згорнути"</string> <string name="close_button_text" msgid="2913281996024033299">"Закрити"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Назад"</string> + <string name="handle_text" msgid="1766582106752184456">"Маркер"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index 0330125c3e6f..ce73bd586c71 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Yoyish"</string> <string name="minimize_button_text" msgid="271592547935841753">"Kichraytirish"</string> <string name="close_button_text" msgid="2913281996024033299">"Yopish"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Orqaga"</string> + <string name="handle_text" msgid="1766582106752184456">"Identifikator"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index 6e4a7682854d..511db6fbc116 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"Phóng to"</string> <string name="minimize_button_text" msgid="271592547935841753">"Thu nhỏ"</string> <string name="close_button_text" msgid="2913281996024033299">"Đóng"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"Quay lại"</string> + <string name="handle_text" msgid="1766582106752184456">"Xử lý"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index df911ed55ab3..16cbf126eff8 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -84,8 +84,6 @@ <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string> <string name="minimize_button_text" msgid="271592547935841753">"最小化"</string> <string name="close_button_text" msgid="2913281996024033299">"关闭"</string> - <!-- no translation found for back_button_text (1469718707134137085) --> - <skip /> - <!-- no translation found for handle_text (1766582106752184456) --> - <skip /> + <string name="back_button_text" msgid="1469718707134137085">"返回"</string> + <string name="handle_text" msgid="1766582106752184456">"处理"</string> </resources> diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index f48402264a73..59d87a0a9371 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -19,7 +19,7 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="pip_phone_close" msgid="5783752637260411309">"Vala"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Nweba"</string> - <string name="pip_phone_settings" msgid="5468987116750491918">"Izilungiselelo"</string> + <string name="pip_phone_settings" msgid="5468987116750491918">"Amasethingi"</string> <string name="pip_phone_enter_split" msgid="7042877263880641911">"Faka ukuhlukanisa isikrini"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Imenyu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"U-<xliff:g id="NAME">%s</xliff:g> ungaphakathi kwesithombe esiphakathi kwesithombe"</string> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java index d6803e8052c6..d3a9a672ec76 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java @@ -52,7 +52,7 @@ public class BubbleBadgeIconFactory extends BaseIconFactory { userBadgedAppIcon = new CircularRingDrawable(userBadgedAppIcon); } Bitmap userBadgedBitmap = createIconBitmap( - userBadgedAppIcon, 1, BITMAP_GENERATION_MODE_WITH_SHADOW); + userBadgedAppIcon, 1, MODE_WITH_SHADOW); return createIconBitmap(userBadgedBitmap); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java index 5dab8a071f76..4ded3ea951e5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java @@ -79,6 +79,6 @@ public class BubbleIconFactory extends BaseIconFactory { true /* shrinkNonAdaptiveIcons */, null /* outscale */, outScale); - return createIconBitmap(icon, outScale[0], BITMAP_GENERATION_MODE_WITH_SHADOW); + return createIconBitmap(icon, outScale[0], MODE_WITH_SHADOW); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index 8cee4f1dc8fb..6ce981e25f5e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -432,7 +432,8 @@ public class SplashscreenContentDrawer { final ShapeIconFactory factory = new ShapeIconFactory( SplashscreenContentDrawer.this.mContext, scaledIconDpi, mFinalIconSize); - final Bitmap bitmap = factory.createScaledBitmapWithoutShadow(iconDrawable); + final Bitmap bitmap = factory.createScaledBitmap(iconDrawable, + BaseIconFactory.MODE_DEFAULT); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); createIconDrawable(new BitmapDrawable(bitmap), true, mHighResIconProvider.mLoadInDetail); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java index e90389764af3..f209521b1da4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/SplitBounds.java @@ -33,6 +33,8 @@ public class SplitBounds implements Parcelable { // This class is orientation-agnostic, so we compute both for later use public final float topTaskPercent; public final float leftTaskPercent; + public final float dividerWidthPercent; + public final float dividerHeightPercent; /** * If {@code true}, that means at the time of creation of this object, the * split-screened apps were vertically stacked. This is useful in scenarios like @@ -62,8 +64,12 @@ public class SplitBounds implements Parcelable { appsStackedVertically = false; } - leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right; - topTaskPercent = this.leftTopBounds.height() / (float) rightBottomBounds.bottom; + float totalWidth = rightBottomBounds.right - leftTopBounds.left; + float totalHeight = rightBottomBounds.bottom - leftTopBounds.top; + leftTaskPercent = leftTopBounds.width() / totalWidth; + topTaskPercent = leftTopBounds.height() / totalHeight; + dividerWidthPercent = visualDividerBounds.width() / totalWidth; + dividerHeightPercent = visualDividerBounds.height() / totalHeight; } public SplitBounds(Parcel parcel) { @@ -75,6 +81,8 @@ public class SplitBounds implements Parcelable { appsStackedVertically = parcel.readBoolean(); leftTopTaskId = parcel.readInt(); rightBottomTaskId = parcel.readInt(); + dividerWidthPercent = parcel.readInt(); + dividerHeightPercent = parcel.readInt(); } @Override @@ -87,6 +95,8 @@ public class SplitBounds implements Parcelable { parcel.writeBoolean(appsStackedVertically); parcel.writeInt(leftTopTaskId); parcel.writeInt(rightBottomTaskId); + parcel.writeFloat(dividerWidthPercent); + parcel.writeFloat(dividerHeightPercent); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java index 7d1f130daaef..9d61c14e1435 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java @@ -101,9 +101,9 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL final int shadowRadiusID = taskInfo.isFocused ? R.dimen.freeform_decor_shadow_focused_thickness : R.dimen.freeform_decor_shadow_unfocused_thickness; - final boolean isFreeform = mTaskInfo.configuration.windowConfiguration.getWindowingMode() - == WindowConfiguration.WINDOWING_MODE_FREEFORM; - final boolean isDragResizeable = isFreeform && mTaskInfo.isResizeable; + final boolean isFreeform = + taskInfo.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_FREEFORM; + final boolean isDragResizeable = isFreeform && taskInfo.isResizeable; WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; @@ -114,6 +114,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL int outsetRightId = R.dimen.freeform_resize_handle; int outsetBottomId = R.dimen.freeform_resize_handle; + mRelayoutParams.reset(); mRelayoutParams.mRunningTaskInfo = taskInfo; mRelayoutParams.mLayoutResId = R.layout.caption_window_decoration; mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index 01cab9aae312..b314163802ca 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -91,7 +91,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> SurfaceControl mTaskBackgroundSurface; SurfaceControl mCaptionContainerSurface; - private CaptionWindowManager mCaptionWindowManager; + private WindowlessWindowManager mCaptionWindowManager; private SurfaceControlViewHost mViewHost; private final Rect mCaptionInsetsRect = new Rect(); @@ -199,13 +199,14 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> } final Rect taskBounds = taskConfig.windowConfiguration.getBounds(); - final int decorContainerOffsetX = -loadResource(params.mOutsetLeftId); - final int decorContainerOffsetY = -loadResource(params.mOutsetTopId); + final Resources resources = mDecorWindowContext.getResources(); + final int decorContainerOffsetX = -loadDimensionPixelSize(resources, params.mOutsetLeftId); + final int decorContainerOffsetY = -loadDimensionPixelSize(resources, params.mOutsetTopId); outResult.mWidth = taskBounds.width() - + loadResource(params.mOutsetRightId) + + loadDimensionPixelSize(resources, params.mOutsetRightId) - decorContainerOffsetX; outResult.mHeight = taskBounds.height() - + loadResource(params.mOutsetBottomId) + + loadDimensionPixelSize(resources, params.mOutsetBottomId) - decorContainerOffsetY; startT.setPosition( mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY) @@ -225,7 +226,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> .build(); } - float shadowRadius = loadResource(params.mShadowRadiusId); + float shadowRadius = loadDimension(resources, params.mShadowRadiusId); int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor(); mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f; mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f; @@ -248,8 +249,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> .build(); } - final int captionHeight = loadResource(params.mCaptionHeightId); - final int captionWidth = loadResource(params.mCaptionWidthId); + final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId); + final int captionWidth = loadDimensionPixelSize(resources, params.mCaptionWidthId); //Prevent caption from going offscreen if task is too high up final int captionYPos = taskBounds.top <= captionHeight / 2 ? 0 : captionHeight / 2; @@ -264,8 +265,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> if (mCaptionWindowManager == null) { // Put caption under a container surface because ViewRootImpl sets the destination frame // of windowless window layers and BLASTBufferQueue#update() doesn't support offset. - mCaptionWindowManager = new CaptionWindowManager( - mTaskInfo.getConfiguration(), mCaptionContainerSurface); + mCaptionWindowManager = new WindowlessWindowManager( + mTaskInfo.getConfiguration(), mCaptionContainerSurface, + null /* hostInputToken */); } // Caption view @@ -309,13 +311,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> .setCrop(mTaskSurface, mTaskSurfaceCrop); } - private int loadResource(int resourceId) { - if (resourceId == Resources.ID_NULL) { - return 0; - } - return mDecorWindowContext.getResources().getDimensionPixelSize(resourceId); - } - /** * Obtains the {@link Display} instance for the display ID in {@link #mTaskInfo} if it exists or * registers {@link #mOnDisplaysChangedListener} if it doesn't. @@ -374,33 +369,18 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> releaseViews(); } - static class RelayoutResult<T extends View & TaskFocusStateConsumer> { - int mWidth; - int mHeight; - T mRootView; - - void reset() { - mWidth = 0; - mHeight = 0; - mRootView = null; - } - } - - private static class CaptionWindowManager extends WindowlessWindowManager { - CaptionWindowManager(Configuration config, SurfaceControl rootSurface) { - super(config, rootSurface, null /* hostInputToken */); - } - - @Override - public void setConfiguration(Configuration configuration) { - super.setConfiguration(configuration); + private static int loadDimensionPixelSize(Resources resources, int resourceId) { + if (resourceId == Resources.ID_NULL) { + return 0; } + return resources.getDimensionPixelSize(resourceId); } - interface SurfaceControlViewHostFactory { - default SurfaceControlViewHost create(Context c, Display d, WindowlessWindowManager wmm) { - return new SurfaceControlViewHost(c, d, wmm); + private static float loadDimension(Resources resources, int resourceId) { + if (resourceId == Resources.ID_NULL) { + return 0; } + return resources.getDimension(resourceId); } static class RelayoutParams{ @@ -433,6 +413,23 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> mOutsetLeftId = Resources.ID_NULL; mOutsetRightId = Resources.ID_NULL; } + } + static class RelayoutResult<T extends View & TaskFocusStateConsumer> { + int mWidth; + int mHeight; + T mRootView; + + void reset() { + mWidth = 0; + mHeight = 0; + mRootView = null; + } + } + + interface SurfaceControlViewHostFactory { + default SurfaceControlViewHost create(Context c, Display d, WindowlessWindowManager wmm) { + return new SurfaceControlViewHost(c, d, wmm); + } } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml new file mode 100644 index 000000000000..8949a75d1a15 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/res/values/dimen.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<resources> + <!-- Resources used in WindowDecorationTests --> + <dimen name="test_freeform_decor_caption_height">32dp</dimen> + <dimen name="test_freeform_decor_caption_width">216dp</dimen> + <dimen name="test_window_decor_left_outset">10dp</dimen> + <dimen name="test_window_decor_top_outset">20dp</dimen> + <dimen name="test_window_decor_right_outset">30dp</dimen> + <dimen name="test_window_decor_bottom_outset">40dp</dimen> + <dimen name="test_window_decor_shadow_radius">5dp</dimen> + <dimen name="test_window_decor_resize_handle">10dp</dimen> +</resources>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java index 103c8dab17d5..4d37e5dbc4dc 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java @@ -50,12 +50,13 @@ import android.view.WindowManager.LayoutParams; import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; -import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.tests.R; import org.junit.Before; import org.junit.Test; @@ -145,8 +146,11 @@ public class WindowDecorationTests extends ShellTestCase { // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is // 64px. taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; - mRelayoutParams.setOutsets(R.dimen.freeform_resize_handle, R.dimen.freeform_resize_handle, - R.dimen.freeform_resize_handle, R.dimen.freeform_resize_handle); + mRelayoutParams.setOutsets( + R.dimen.test_window_decor_left_outset, + R.dimen.test_window_decor_top_outset, + R.dimen.test_window_decor_right_outset, + R.dimen.test_window_decor_bottom_outset); final SurfaceControl taskSurface = mock(SurfaceControl.class); final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface); @@ -196,13 +200,11 @@ public class WindowDecorationTests extends ShellTestCase { // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is // 64px. taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; -// int outsetLeftId = R.dimen.split_divider_bar_width; -// int outsetTopId = R.dimen.gestures_onehanded_drag_threshold; -// int outsetRightId = R.dimen.freeform_resize_handle; -// int outsetBottomId = R.dimen.bubble_dismiss_target_padding_x; -// mRelayoutParams.setOutsets(outsetLeftId, outsetTopId, outsetRightId, outsetBottomId); - mRelayoutParams.setOutsets(R.dimen.freeform_resize_handle, R.dimen.freeform_resize_handle, - R.dimen.freeform_resize_handle, R.dimen.freeform_resize_handle); + mRelayoutParams.setOutsets( + R.dimen.test_window_decor_left_outset, + R.dimen.test_window_decor_top_outset, + R.dimen.test_window_decor_right_outset, + R.dimen.test_window_decor_bottom_outset); final SurfaceControl taskSurface = mock(SurfaceControl.class); final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface); @@ -211,8 +213,8 @@ public class WindowDecorationTests extends ShellTestCase { verify(decorContainerSurfaceBuilder).setParent(taskSurface); verify(decorContainerSurfaceBuilder).setContainerLayer(); verify(mMockSurfaceControlStartT).setTrustedOverlay(decorContainerSurface, true); - verify(mMockSurfaceControlStartT).setPosition(decorContainerSurface, -60, -60); - verify(mMockSurfaceControlStartT).setWindowCrop(decorContainerSurface, 420, 220); + verify(mMockSurfaceControlStartT).setPosition(decorContainerSurface, -20, -40); + verify(mMockSurfaceControlStartT).setWindowCrop(decorContainerSurface, 380, 220); verify(taskBackgroundSurfaceBuilder).setParent(taskSurface); verify(taskBackgroundSurfaceBuilder).setEffectLayer(); @@ -225,36 +227,34 @@ public class WindowDecorationTests extends ShellTestCase { verify(captionContainerSurfaceBuilder).setParent(decorContainerSurface); verify(captionContainerSurfaceBuilder).setContainerLayer(); - verify(mMockSurfaceControlStartT).setPosition(captionContainerSurface, -6, -156); - verify(mMockSurfaceControlStartT).setWindowCrop(captionContainerSurface, 300, 432); + verify(mMockSurfaceControlStartT).setPosition(captionContainerSurface, -46, 8); + verify(mMockSurfaceControlStartT).setWindowCrop(captionContainerSurface, 300, 64); verify(mMockSurfaceControlStartT).show(captionContainerSurface); verify(mMockSurfaceControlViewHostFactory).create(any(), eq(defaultDisplay), any()); verify(mMockSurfaceControlViewHost) .setView(same(mMockView), - argThat(lp -> lp.height == 432 + argThat(lp -> lp.height == 64 && lp.width == 432 && (lp.flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0)); if (ViewRootImpl.CAPTION_ON_SHELL) { verify(mMockView).setTaskFocusState(true); verify(mMockWindowContainerTransaction) .addRectInsetsProvider(taskInfo.token, - new Rect(100, 300, 400, 516), + new Rect(100, 300, 400, 332), new int[] { InsetsState.ITYPE_CAPTION_BAR }); } verify(mMockSurfaceControlFinishT) .setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y); verify(mMockSurfaceControlFinishT) - .setCrop(taskSurface, new Rect(-60, -60, 360, 160)); + .setCrop(taskSurface, new Rect(-20, -40, 360, 180)); verify(mMockSurfaceControlStartT) .show(taskSurface); - assertEquals(420, mRelayoutResult.mWidth); + assertEquals(380, mRelayoutResult.mWidth); assertEquals(220, mRelayoutResult.mHeight); - - } @Test @@ -293,8 +293,11 @@ public class WindowDecorationTests extends ShellTestCase { // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is // 64px. taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; - mRelayoutParams.setOutsets(R.dimen.freeform_resize_handle, R.dimen.freeform_resize_handle, - R.dimen.freeform_resize_handle, R.dimen.freeform_resize_handle); + mRelayoutParams.setOutsets( + R.dimen.test_window_decor_left_outset, + R.dimen.test_window_decor_top_outset, + R.dimen.test_window_decor_right_outset, + R.dimen.test_window_decor_bottom_outset); final SurfaceControl taskSurface = mock(SurfaceControl.class); final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface); @@ -365,7 +368,8 @@ public class WindowDecorationTests extends ShellTestCase { private TestWindowDecoration createWindowDecoration( ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) { - return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer, + return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(), + mMockDisplayController, mMockShellTaskOrganizer, taskInfo, testSurface, new MockObjectSupplier<>(mMockSurfaceControlBuilders, () -> createMockSurfaceControlBuilder(mock(SurfaceControl.class))), @@ -417,12 +421,10 @@ public class WindowDecorationTests extends ShellTestCase { @Override void relayout(ActivityManager.RunningTaskInfo taskInfo) { - mRelayoutParams.mLayoutResId = 0; - mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_width; - mRelayoutParams.mCaptionWidthId = R.dimen.freeform_decor_caption_width; - mRelayoutParams.mShadowRadiusId = - R.dimen.freeform_decor_shadow_unfocused_thickness; + mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height; + mRelayoutParams.mCaptionWidthId = R.dimen.test_freeform_decor_caption_width; + mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius; relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT, mMockWindowContainerTransaction, mMockView, mRelayoutResult); diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml index 18b8ca9b4dd6..77dfbeee9bbf 100644 --- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml +++ b/packages/CompanionDeviceManager/res/values-zh-rTW/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_label" msgid="4470785958457506021">"隨附裝置管理員"</string> + <string name="app_label" msgid="4470785958457506021">"隨附裝置管理工具"</string> <string name="confirmation_title" msgid="3785000297483688997">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>存取「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>"</string> <string name="profile_name_watch" msgid="576290739483672360">"手錶"</string> <string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」<strong></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/MobileNetworkTypeIconsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/MobileNetworkTypeIconsTest.java index 39977dfa5c80..f969a63dc663 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/MobileNetworkTypeIconsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/MobileNetworkTypeIconsTest.java @@ -41,19 +41,19 @@ public class MobileNetworkTypeIconsTest { MobileNetworkTypeIcon icon = MobileNetworkTypeIcons.getNetworkTypeIcon(TelephonyIcons.FOUR_G); - assertThat(icon.getName()).isEqualTo(TelephonyIcons.H_PLUS.name); + assertThat(icon.getName()).isEqualTo(TelephonyIcons.FOUR_G.name); assertThat(icon.getIconResId()).isEqualTo(TelephonyIcons.ICON_4G); } @Test public void getNetworkTypeIcon_unknown_returnsUnknown() { - SignalIcon.MobileIconGroup unknownGroup = - new SignalIcon.MobileIconGroup("testUnknownNameHere", 45, 6); + SignalIcon.MobileIconGroup unknownGroup = new SignalIcon.MobileIconGroup( + "testUnknownNameHere", /* dataContentDesc= */ 45, /* dataType= */ 6); MobileNetworkTypeIcon icon = MobileNetworkTypeIcons.getNetworkTypeIcon(unknownGroup); assertThat(icon.getName()).isEqualTo("testUnknownNameHere"); - assertThat(icon.getIconResId()).isEqualTo(45); - assertThat(icon.getContentDescriptionResId()).isEqualTo(6); + assertThat(icon.getIconResId()).isEqualTo(6); + assertThat(icon.getContentDescriptionResId()).isEqualTo(45); } } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt index ca36fa43da76..fdfad2bc2fa1 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt @@ -25,7 +25,6 @@ import android.graphics.Rect import android.os.Looper import android.util.Log import android.util.MathUtils -import android.view.GhostView import android.view.View import android.view.ViewGroup import android.view.ViewGroup.LayoutParams.MATCH_PARENT @@ -86,6 +85,9 @@ constructor( */ val sourceIdentity: Any + /** The CUJ associated to this controller. */ + val cuj: DialogCuj? + /** * Move the drawing of the source in the overlay of [viewGroup]. * @@ -142,7 +144,31 @@ constructor( * controlled by this controller. */ // TODO(b/252723237): Make this non-nullable - fun jankConfigurationBuilder(cuj: Int): InteractionJankMonitor.Configuration.Builder? + fun jankConfigurationBuilder(): InteractionJankMonitor.Configuration.Builder? + + companion object { + /** + * Create a [Controller] that can animate [source] to and from a dialog. + * + * Important: The view must be attached to a [ViewGroup] when calling this function and + * during the animation. For safety, this method will return null when it is not. + * + * Note: The background of [view] should be a (rounded) rectangle so that it can be + * properly animated. + */ + fun fromView(source: View, cuj: DialogCuj? = null): Controller? { + if (source.parent !is ViewGroup) { + Log.e( + TAG, + "Skipping animation as view $source is not attached to a ViewGroup", + Exception(), + ) + return null + } + + return ViewDialogLaunchAnimatorController(source, cuj) + } + } } /** @@ -172,7 +198,12 @@ constructor( cuj: DialogCuj? = null, animateBackgroundBoundsChange: Boolean = false ) { - show(dialog, createController(view), cuj, animateBackgroundBoundsChange) + val controller = Controller.fromView(view, cuj) + if (controller == null) { + dialog.show() + } else { + show(dialog, controller, animateBackgroundBoundsChange) + } } /** @@ -187,10 +218,10 @@ constructor( * Caveats: When calling this function and [dialog] is not a fullscreen dialog, then it will be * made fullscreen and 2 views will be inserted between the dialog DecorView and its children. */ + @JvmOverloads fun show( dialog: Dialog, controller: Controller, - cuj: DialogCuj? = null, animateBackgroundBoundsChange: Boolean = false ) { if (Looper.myLooper() != Looper.getMainLooper()) { @@ -207,7 +238,10 @@ constructor( it.dialog.window.decorView.viewRootImpl == controller.viewRoot } val animateFrom = - animatedParent?.dialogContentWithBackground?.let { createController(it) } ?: controller + animatedParent?.dialogContentWithBackground?.let { + Controller.fromView(it, controller.cuj) + } + ?: controller if (animatedParent == null && animateFrom !is LaunchableView) { // Make sure the View we launch from implements LaunchableView to avoid visibility @@ -244,96 +278,12 @@ constructor( animateBackgroundBoundsChange, animatedParent, isForTesting, - cuj, ) openedDialogs.add(animatedDialog) animatedDialog.start() } - /** Create a [Controller] that can animate [source] to & from a dialog. */ - private fun createController(source: View): Controller { - return object : Controller { - override val viewRoot: ViewRootImpl - get() = source.viewRootImpl - - override val sourceIdentity: Any = source - - override fun startDrawingInOverlayOf(viewGroup: ViewGroup) { - // Create a temporary ghost of the source (which will make it invisible) and add it - // to the host dialog. - GhostView.addGhost(source, viewGroup) - - // The ghost of the source was just created, so the source is currently invisible. - // We need to make sure that it stays invisible as long as the dialog is shown or - // animating. - (source as? LaunchableView)?.setShouldBlockVisibilityChanges(true) - } - - override fun stopDrawingInOverlay() { - // Note: here we should remove the ghost from the overlay, but in practice this is - // already done by the launch controllers created below. - - // Make sure we allow the source to change its visibility again. - (source as? LaunchableView)?.setShouldBlockVisibilityChanges(false) - source.visibility = View.VISIBLE - } - - override fun createLaunchController(): LaunchAnimator.Controller { - val delegate = GhostedViewLaunchAnimatorController(source) - return object : LaunchAnimator.Controller by delegate { - override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { - // Remove the temporary ghost added by [startDrawingInOverlayOf]. Another - // ghost (that ghosts only the source content, and not its background) will - // be added right after this by the delegate and will be animated. - GhostView.removeGhost(source) - delegate.onLaunchAnimationStart(isExpandingFullyAbove) - } - - override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { - delegate.onLaunchAnimationEnd(isExpandingFullyAbove) - - // We hide the source when the dialog is showing. We will make this view - // visible again when dismissing the dialog. This does nothing if the source - // implements [LaunchableView], as it's already INVISIBLE in that case. - source.visibility = View.INVISIBLE - } - } - } - - override fun createExitController(): LaunchAnimator.Controller { - return GhostedViewLaunchAnimatorController(source) - } - - override fun shouldAnimateExit(): Boolean { - // The source should be invisible by now, if it's not then something else changed - // its visibility and we probably don't want to run the animation. - if (source.visibility != View.INVISIBLE) { - return false - } - - return source.isAttachedToWindow && ((source.parent as? View)?.isShown ?: true) - } - - override fun onExitAnimationCancelled() { - // Make sure we allow the source to change its visibility again. - (source as? LaunchableView)?.setShouldBlockVisibilityChanges(false) - - // If the view is invisible it's probably because of us, so we make it visible - // again. - if (source.visibility == View.INVISIBLE) { - source.visibility = View.VISIBLE - } - } - - override fun jankConfigurationBuilder( - cuj: Int - ): InteractionJankMonitor.Configuration.Builder? { - return InteractionJankMonitor.Configuration.Builder.withView(cuj, source) - } - } - } - /** * Launch [dialog] from [another dialog][animateFrom] that was shown using [show]. This will * allow for dismissing the whole stack. @@ -563,9 +513,6 @@ private class AnimatedDialog( * Whether synchronization should be disabled, which can be useful if we are running in a test. */ private val forceDisableSynchronization: Boolean, - - /** Interaction to which the dialog animation is associated. */ - private val cuj: DialogCuj? = null ) { /** * The DecorView of this dialog window. @@ -618,8 +565,9 @@ private class AnimatedDialog( private var hasInstrumentedJank = false fun start() { + val cuj = controller.cuj if (cuj != null) { - val config = controller.jankConfigurationBuilder(cuj.cujType) + val config = controller.jankConfigurationBuilder() if (config != null) { if (cuj.tag != null) { config.setTag(cuj.tag) @@ -917,7 +865,7 @@ private class AnimatedDialog( } if (hasInstrumentedJank) { - interactionJankMonitor.end(cuj!!.cujType) + interactionJankMonitor.end(controller.cuj!!.cujType) } } ) diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt index 8ce372dbb278..40a5e9794d37 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt @@ -30,7 +30,12 @@ interface Expandable { */ fun activityLaunchController(cujType: Int? = null): ActivityLaunchAnimator.Controller? - // TODO(b/230830644): Introduce DialogLaunchAnimator and a function to expose it here. + /** + * Create a [DialogLaunchAnimator.Controller] that can be used to expand this [Expandable] into + * a Dialog, or return `null` if this [Expandable] should not be animated (e.g. if it is + * currently not attached or visible). + */ + fun dialogLaunchController(cuj: DialogCuj? = null): DialogLaunchAnimator.Controller? companion object { /** @@ -39,6 +44,7 @@ interface Expandable { * Note: The background of [view] should be a (rounded) rectangle so that it can be properly * animated. */ + @JvmStatic fun fromView(view: View): Expandable { return object : Expandable { override fun activityLaunchController( @@ -46,6 +52,12 @@ interface Expandable { ): ActivityLaunchAnimator.Controller? { return ActivityLaunchAnimator.Controller.fromView(view, cujType) } + + override fun dialogLaunchController( + cuj: DialogCuj? + ): DialogLaunchAnimator.Controller? { + return DialogLaunchAnimator.Controller.fromView(view, cuj) + } } } } diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt index f79b328190dd..5f1bb83715c2 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt @@ -89,6 +89,11 @@ class TextAnimator( var y: Float = 0f /** + * The current line of text being drawn, in a multi-line TextView. + */ + var lineNo: Int = 0 + + /** * Mutable text size of the glyph in pixels. */ var textSize: Float = 0f diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt index d427a57f3b87..0448c818f765 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt @@ -244,7 +244,7 @@ class TextInterpolator( canvas.translate(origin, layout.getLineBaseline(lineNo).toFloat()) run.fontRuns.forEach { fontRun -> - drawFontRun(canvas, run, fontRun, tmpPaint) + drawFontRun(canvas, run, fontRun, lineNo, tmpPaint) } } finally { canvas.restore() @@ -349,7 +349,7 @@ class TextInterpolator( var glyphFilter: GlyphCallback? = null // Draws single font run. - private fun drawFontRun(c: Canvas, line: Run, run: FontRun, paint: Paint) { + private fun drawFontRun(c: Canvas, line: Run, run: FontRun, lineNo: Int, paint: Paint) { var arrayIndex = 0 val font = fontInterpolator.lerp(run.baseFont, run.targetFont, progress) @@ -368,11 +368,13 @@ class TextInterpolator( tmpGlyph.font = font tmpGlyph.runStart = run.start tmpGlyph.runLength = run.end - run.start + tmpGlyph.lineNo = lineNo tmpPaintForGlyph.set(paint) var prevStart = run.start for (i in run.start until run.end) { + tmpGlyph.glyphIndex = i tmpGlyph.glyphId = line.glyphIds[i] tmpGlyph.x = MathUtils.lerp(line.baseX[i], line.targetX[i], progress) tmpGlyph.y = MathUtils.lerp(line.baseY[i], line.targetY[i], progress) diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt new file mode 100644 index 000000000000..ecee598afe4e --- /dev/null +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt @@ -0,0 +1,107 @@ +/* + * 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.systemui.animation + +import android.view.GhostView +import android.view.View +import android.view.ViewGroup +import android.view.ViewRootImpl +import com.android.internal.jank.InteractionJankMonitor + +/** A [DialogLaunchAnimator.Controller] that can animate a [View] from/to a dialog. */ +class ViewDialogLaunchAnimatorController +internal constructor( + private val source: View, + override val cuj: DialogCuj?, +) : DialogLaunchAnimator.Controller { + override val viewRoot: ViewRootImpl + get() = source.viewRootImpl + + override val sourceIdentity: Any = source + + override fun startDrawingInOverlayOf(viewGroup: ViewGroup) { + // Create a temporary ghost of the source (which will make it invisible) and add it + // to the host dialog. + GhostView.addGhost(source, viewGroup) + + // The ghost of the source was just created, so the source is currently invisible. + // We need to make sure that it stays invisible as long as the dialog is shown or + // animating. + (source as? LaunchableView)?.setShouldBlockVisibilityChanges(true) + } + + override fun stopDrawingInOverlay() { + // Note: here we should remove the ghost from the overlay, but in practice this is + // already done by the launch controllers created below. + + // Make sure we allow the source to change its visibility again. + (source as? LaunchableView)?.setShouldBlockVisibilityChanges(false) + source.visibility = View.VISIBLE + } + + override fun createLaunchController(): LaunchAnimator.Controller { + val delegate = GhostedViewLaunchAnimatorController(source) + return object : LaunchAnimator.Controller by delegate { + override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { + // Remove the temporary ghost added by [startDrawingInOverlayOf]. Another + // ghost (that ghosts only the source content, and not its background) will + // be added right after this by the delegate and will be animated. + GhostView.removeGhost(source) + delegate.onLaunchAnimationStart(isExpandingFullyAbove) + } + + override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) { + delegate.onLaunchAnimationEnd(isExpandingFullyAbove) + + // We hide the source when the dialog is showing. We will make this view + // visible again when dismissing the dialog. This does nothing if the source + // implements [LaunchableView], as it's already INVISIBLE in that case. + source.visibility = View.INVISIBLE + } + } + } + + override fun createExitController(): LaunchAnimator.Controller { + return GhostedViewLaunchAnimatorController(source) + } + + override fun shouldAnimateExit(): Boolean { + // The source should be invisible by now, if it's not then something else changed + // its visibility and we probably don't want to run the animation. + if (source.visibility != View.INVISIBLE) { + return false + } + + return source.isAttachedToWindow && ((source.parent as? View)?.isShown ?: true) + } + + override fun onExitAnimationCancelled() { + // Make sure we allow the source to change its visibility again. + (source as? LaunchableView)?.setShouldBlockVisibilityChanges(false) + + // If the view is invisible it's probably because of us, so we make it visible + // again. + if (source.visibility == View.INVISIBLE) { + source.visibility = View.VISIBLE + } + } + + override fun jankConfigurationBuilder(): InteractionJankMonitor.Configuration.Builder? { + val type = cuj?.cujType ?: return null + return InteractionJankMonitor.Configuration.Builder.withView(type, source) + } +} diff --git a/packages/SystemUI/checks/Android.bp b/packages/SystemUI/checks/Android.bp index 8457312dc403..cf66ff60f9ab 100644 --- a/packages/SystemUI/checks/Android.bp +++ b/packages/SystemUI/checks/Android.bp @@ -40,6 +40,10 @@ java_test_host { "tests/**/*.kt", "tests/**/*.java", ], + data: [ + ":framework", + ":androidx.annotation_annotation", + ], static_libs: [ "SystemUILintChecker", "junit", diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt index 4eeeb850292a..4b9aa13c0240 100644 --- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt +++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt @@ -32,7 +32,8 @@ import org.jetbrains.uast.UReferenceExpression class SoftwareBitmapDetector : Detector(), SourceCodeScanner { override fun getApplicableReferenceNames(): List<String> { - return mutableListOf("ALPHA_8", "RGB_565", "ARGB_8888", "RGBA_F16", "RGBA_1010102") + return mutableListOf( + "ALPHA_8", "RGB_565", "ARGB_4444", "ARGB_8888", "RGBA_F16", "RGBA_1010102") } override fun visitReference( @@ -40,13 +41,12 @@ class SoftwareBitmapDetector : Detector(), SourceCodeScanner { reference: UReferenceExpression, referenced: PsiElement ) { - val evaluator = context.evaluator if (evaluator.isMemberInClass(referenced as? PsiField, "android.graphics.Bitmap.Config")) { context.report( ISSUE, referenced, - context.getNameLocation(referenced), + context.getNameLocation(reference), "Replace software bitmap with `Config.HARDWARE`" ) } diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt index d4c55c0d9149..141dd0535986 100644 --- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt +++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt @@ -18,185 +18,22 @@ package com.android.internal.systemui.lint import com.android.annotations.NonNull import com.android.tools.lint.checks.infrastructure.LintDetectorTest.java +import com.android.tools.lint.checks.infrastructure.TestFiles.LibraryReferenceTestFile +import java.io.File import org.intellij.lang.annotations.Language @Suppress("UnstableApiUsage") @NonNull private fun indentedJava(@NonNull @Language("JAVA") source: String) = java(source).indented() -internal val commonSettingsCode = - """ -public static float getFloat(ContentResolver cr, String name) { return 0.0f; } -public static long getLong(ContentResolver cr, String name) { - return 0L; -} -public static int getInt(ContentResolver cr, String name) { - return 0; -} -public static String getString(ContentResolver cr, String name) { - return ""; -} -public static float getFloat(ContentResolver cr, String name, float def) { - return 0.0f; -} -public static long getLong(ContentResolver cr, String name, long def) { - return 0L; -} -public static int getInt(ContentResolver cr, String name, int def) { - return 0; -} -public static String getString(ContentResolver cr, String name, String def) { - return ""; -} -public static boolean putFloat(ContentResolver cr, String name, float value) { - return true; -} -public static boolean putLong(ContentResolver cr, String name, long value) { - return true; -} -public static boolean putInt(ContentResolver cr, String name, int value) { - return true; -} -public static boolean putFloat(ContentResolver cr, String name) { - return true; -} -public static boolean putString(ContentResolver cr, String name, String value) { - return true; -} -""" - /* * This file contains stubs of framework APIs and System UI classes for testing purposes only. The * stubs are not used in the lint detectors themselves. */ internal val androidStubs = arrayOf( - indentedJava( - """ -package android.app; - -public class ActivityManager { - public static int getCurrentUser() {} -} -""" - ), - indentedJava( - """ -package android.accounts; - -public class AccountManager { - public static AccountManager get(Context context) { return null; } -} -""" - ), - indentedJava( - """ -package android.os; -import android.content.pm.UserInfo; -import android.annotation.UserIdInt; - -public class UserManager { - public UserInfo getUserInfo(@UserIdInt int userId) {} -} -""" - ), - indentedJava(""" -package android.annotation; - -public @interface UserIdInt {} -"""), - indentedJava(""" -package android.content.pm; - -public class UserInfo {} -"""), - indentedJava(""" -package android.os; - -public class Looper {} -"""), - indentedJava(""" -package android.os; - -public class Handler {} -"""), - indentedJava(""" -package android.content; - -public class ServiceConnection {} -"""), - indentedJava(""" -package android.os; - -public enum UserHandle { - ALL -} -"""), - indentedJava( - """ -package android.content; -import android.os.UserHandle; -import android.os.Handler; -import android.os.Looper; -import java.util.concurrent.Executor; - -public class Context { - public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {} - public void registerReceiverAsUser( - BroadcastReceiver receiver, UserHandle user, IntentFilter filter, - String broadcastPermission, Handler scheduler) {} - public void registerReceiverForAllUsers( - BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, - Handler scheduler) {} - public void sendBroadcast(Intent intent) {} - public void sendBroadcast(Intent intent, String receiverPermission) {} - public void sendBroadcastAsUser(Intent intent, UserHandle userHandle, String permission) {} - public void bindService(Intent intent) {} - public void bindServiceAsUser( - Intent intent, ServiceConnection connection, int flags, UserHandle userHandle) {} - public void unbindService(ServiceConnection connection) {} - public Looper getMainLooper() { return null; } - public Executor getMainExecutor() { return null; } - public Handler getMainThreadHandler() { return null; } - public final @Nullable <T> T getSystemService(@NonNull Class<T> serviceClass) { return null; } - public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name); -} -""" - ), - indentedJava( - """ -package android.app; -import android.content.Context; - -public class Activity extends Context {} -""" - ), - indentedJava( - """ -package android.graphics; - -public class Bitmap { - public enum Config { - ARGB_8888, - RGB_565, - HARDWARE - } - public static Bitmap createBitmap(int width, int height, Config config) { - return null; - } -} -""" - ), - indentedJava(""" -package android.content; - -public class BroadcastReceiver {} -"""), - indentedJava(""" -package android.content; - -public class IntentFilter {} -"""), + LibraryReferenceTestFile(File("framework.jar").canonicalFile), + LibraryReferenceTestFile(File("androidx.annotation_annotation.jar").canonicalFile), indentedJava( """ package com.android.systemui.settings; @@ -208,47 +45,4 @@ public interface UserTracker { } """ ), - indentedJava( - """ -package androidx.annotation; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.CONSTRUCTOR; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -@Retention(SOURCE) -@Target({METHOD,CONSTRUCTOR,TYPE,PARAMETER}) -public @interface WorkerThread { -} -""" - ), - indentedJava( - """ -package android.provider; - -public class Settings { - public static final class Global { - public static final String UNLOCK_SOUND = "unlock_sound"; - """ + - commonSettingsCode + - """ - } - public static final class Secure { - """ + - commonSettingsCode + - """ - } - public static final class System { - """ + - commonSettingsCode + - """ - } -} -""" - ), ) diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SoftwareBitmapDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SoftwareBitmapDetectorTest.kt index 090ddf88fa3c..c632636eb9c8 100644 --- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SoftwareBitmapDetectorTest.kt +++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SoftwareBitmapDetectorTest.kt @@ -51,12 +51,12 @@ class SoftwareBitmapDetectorTest : SystemUILintDetectorTest() { .run() .expect( """ - src/android/graphics/Bitmap.java:5: Warning: Replace software bitmap with Config.HARDWARE [SoftwareBitmap] - ARGB_8888, - ~~~~~~~~~ - src/android/graphics/Bitmap.java:6: Warning: Replace software bitmap with Config.HARDWARE [SoftwareBitmap] - RGB_565, - ~~~~~~~ + src/TestClass.java:5: Warning: Replace software bitmap with Config.HARDWARE [SoftwareBitmap] + Bitmap.createBitmap(300, 300, Bitmap.Config.RGB_565); + ~~~~~~~ + src/TestClass.java:6: Warning: Replace software bitmap with Config.HARDWARE [SoftwareBitmap] + Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888); + ~~~~~~~~~ 0 errors, 2 warnings """ ) @@ -67,7 +67,7 @@ class SoftwareBitmapDetectorTest : SystemUILintDetectorTest() { lint() .files( TestFiles.java( - """ + """ import android.graphics.Bitmap; public class TestClass { @@ -76,8 +76,7 @@ class SoftwareBitmapDetectorTest : SystemUILintDetectorTest() { } } """ - ) - .indented(), + ), *stubs ) .issues(SoftwareBitmapDetector.ISSUE) diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt index 2183b3805eed..3f93f075fe8b 100644 --- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt +++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt @@ -3,9 +3,42 @@ package com.android.internal.systemui.lint import com.android.tools.lint.checks.infrastructure.LintDetectorTest import com.android.tools.lint.checks.infrastructure.TestLintTask import java.io.File +import org.junit.ClassRule +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.runners.model.Statement @Suppress("UnstableApiUsage") +@RunWith(JUnit4::class) abstract class SystemUILintDetectorTest : LintDetectorTest() { + + companion object { + @ClassRule + @JvmField + val libraryChecker: LibraryExists = + LibraryExists("framework.jar", "androidx.annotation_annotation.jar") + } + + class LibraryExists(vararg val libraryNames: String) : TestRule { + override fun apply(base: Statement, description: Description): Statement { + return object : Statement() { + override fun evaluate() { + for (libName in libraryNames) { + val libFile = File(libName) + if (!libFile.canonicalFile.exists()) { + throw Exception( + "Could not find $libName in the test's working directory. " + + "File ${libFile.absolutePath} does not exist." + ) + } + } + base.evaluate() + } + } + } + } /** * Customize the lint task to disable SDK usage completely. This ensures that running the tests * in Android Studio has the same result as running the tests in atest diff --git a/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt index 065c3149c2f5..50c3d7e1e76b 100644 --- a/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt +++ b/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt @@ -40,17 +40,16 @@ import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection import com.android.internal.jank.InteractionJankMonitor import com.android.systemui.animation.ActivityLaunchAnimator +import com.android.systemui.animation.DialogCuj import com.android.systemui.animation.DialogLaunchAnimator +import com.android.systemui.animation.Expandable import com.android.systemui.animation.LaunchAnimator import kotlin.math.roundToInt -/** A controller that can control animated launches. */ +/** A controller that can control animated launches from an [Expandable]. */ interface ExpandableController { - /** Create an [ActivityLaunchAnimator.Controller] to animate into an Activity. */ - fun forActivity(): ActivityLaunchAnimator.Controller - - /** Create a [DialogLaunchAnimator.Controller] to animate into a Dialog. */ - fun forDialog(): DialogLaunchAnimator.Controller + /** The [Expandable] controlled by this controller. */ + val expandable: Expandable } /** @@ -120,13 +119,26 @@ internal class ExpandableControllerImpl( private val layoutDirection: LayoutDirection, private val isComposed: State<Boolean>, ) : ExpandableController { - override fun forActivity(): ActivityLaunchAnimator.Controller { - return activityController() - } + override val expandable: Expandable = + object : Expandable { + override fun activityLaunchController( + cujType: Int?, + ): ActivityLaunchAnimator.Controller? { + if (!isComposed.value) { + return null + } - override fun forDialog(): DialogLaunchAnimator.Controller { - return dialogController() - } + return activityController(cujType) + } + + override fun dialogLaunchController(cuj: DialogCuj?): DialogLaunchAnimator.Controller? { + if (!isComposed.value) { + return null + } + + return dialogController(cuj) + } + } /** * Create a [LaunchAnimator.Controller] that is going to be used to drive an activity or dialog @@ -233,7 +245,7 @@ internal class ExpandableControllerImpl( } /** Create an [ActivityLaunchAnimator.Controller] that can be used to animate activities. */ - private fun activityController(): ActivityLaunchAnimator.Controller { + private fun activityController(cujType: Int?): ActivityLaunchAnimator.Controller { val delegate = launchController() return object : ActivityLaunchAnimator.Controller, LaunchAnimator.Controller by delegate { override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { @@ -248,10 +260,11 @@ internal class ExpandableControllerImpl( } } - private fun dialogController(): DialogLaunchAnimator.Controller { + private fun dialogController(cuj: DialogCuj?): DialogLaunchAnimator.Controller { return object : DialogLaunchAnimator.Controller { override val viewRoot: ViewRootImpl = composeViewRoot.viewRootImpl override val sourceIdentity: Any = this@ExpandableControllerImpl + override val cuj: DialogCuj? = cuj override fun startDrawingInOverlayOf(viewGroup: ViewGroup) { val newOverlay = viewGroup.overlay as ViewGroupOverlay @@ -294,9 +307,7 @@ internal class ExpandableControllerImpl( isDialogShowing.value = false } - override fun jankConfigurationBuilder( - cuj: Int - ): InteractionJankMonitor.Configuration.Builder? { + override fun jankConfigurationBuilder(): InteractionJankMonitor.Configuration.Builder? { // TODO(b/252723237): Add support for jank monitoring when animating from a // Composable. return null diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt index 1e74c3d68efc..dabb43b6074d 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt @@ -14,6 +14,7 @@ package com.android.systemui.plugins import android.content.res.Resources +import android.graphics.Rect import android.graphics.drawable.Drawable import android.view.View import com.android.systemui.plugins.annotations.ProvidesInterface @@ -114,6 +115,17 @@ interface ClockAnimations { /** Runs the battery animation (if any). */ fun charge() { } + + /** Move the clock, for example, if the notification tray appears in split-shade mode. */ + fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) { } + + /** + * Whether this clock has a custom position update animation. If true, the keyguard will call + * `onPositionUpdated` to notify the clock of a position update animation. If false, a default + * animation will be used (e.g. a simple translation). + */ + val hasCustomPositionUpdatedAnimation + get() = false } /** Events that have specific data about the related face */ diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index 3ad7c8c4369c..d64587dcf362 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -37,6 +37,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="@dimen/keyguard_large_clock_top_margin" + android:clipChildren="false" android:visibility="gone" /> <!-- Not quite optimal but needed to translate these items as a group. The diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml index d5e84f9e30eb..d5552f6ad44f 100644 --- a/packages/SystemUI/res-keyguard/values-af/strings.xml +++ b/packages/SystemUI/res-keyguard/values-af/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Patroon word vereis nadat toestel herbegin het"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN word vereis nadat toestel herbegin het"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Wagwoord word vereis nadat toestel herbegin het"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Patroon word vir bykomende sekuriteit vereis"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN word vir bykomende sekuriteit vereis"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Wagwoord word vir bykomende sekuriteit vereis"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Toestel is deur administrateur gesluit"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Toestel is handmatig gesluit"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nie herken nie"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Verstek"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Borrel"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analoog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml index be52c448181d..533e5a299e4c 100644 --- a/packages/SystemUI/res-keyguard/values-am/strings.xml +++ b/packages/SystemUI/res-keyguard/values-am/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"መሣሪያ ዳግም ከጀመረ በኋላ ሥርዓተ ጥለት ያስፈልጋል"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"መሣሪያ ዳግም ከተነሳ በኋላ ፒን ያስፈልጋል"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"መሣሪያ ዳግም ከጀመረ በኋላ የይለፍ ቃል ያስፈልጋል"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ሥርዓተ ጥለት ለተጨማሪ ደህንነት ያስፈልጋል"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ፒን ለተጨማሪ ደህንነት ያስፈልጋል"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"የይለፍ ቃል ለተጨማሪ ደህንነት ያስፈልጋል"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"መሣሪያ በአስተዳዳሪ ተቆልፏል"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"መሣሪያ በተጠቃሚው ራሱ ተቆልፏል"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"አልታወቀም"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ነባሪ"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"አረፋ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"አናሎግ"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml index adb57b6d4d67..81ce7d3c9361 100644 --- a/packages/SystemUI/res-keyguard/values-ar/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"يجب رسم النقش بعد إعادة تشغيل الجهاز"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"يجب إدخال رقم التعريف الشخصي بعد إعادة تشغيل الجهاز"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"يجب إدخال كلمة المرور بعد إعادة تشغيل الجهاز"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"يجب رسم النقش لمزيد من الأمان"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"يجب إدخال رقم التعريف الشخصي لمزيد من الأمان"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"يجب إدخال كلمة المرور لمزيد من الأمان"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"اختار المشرف قفل الجهاز"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"تم حظر الجهاز يدويًا"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"لم يتم التعرّف عليه."</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"تلقائي"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"فقاعة"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ساعة تقليدية"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml index cbfb325fa9b3..443f666c0faa 100644 --- a/packages/SystemUI/res-keyguard/values-as/strings.xml +++ b/packages/SystemUI/res-keyguard/values-as/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত আৰ্হি দিয়াটো বাধ্যতামূলক"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত পিন দিয়াটো বাধ্যতামূলক"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পাছত পাছৱৰ্ড দিয়াটো বাধ্যতামূলক"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"অতিৰিক্ত সুৰক্ষাৰ বাবে আর্হি দিয়াটো বাধ্যতামূলক"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"অতিৰিক্ত সুৰক্ষাৰ বাবে পিন দিয়াটো বাধ্যতামূলক"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"অতিৰিক্ত সুৰক্ষাৰ বাবে পাছৱর্ড দিয়াটো বাধ্যতামূলক"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"প্ৰশাসকে ডিভাইচ লক কৰি ৰাখিছে"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ডিভাইচটো মেনুৱেলভাৱে লক কৰা হৈছিল"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"চিনাক্ত কৰিব পৰা নাই"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ডিফ’ল্ট"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"বাবল"</string> <string name="clock_title_analog" msgid="8409262532900918273">"এনাল’গ"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml index 6ec1061ac8bb..e12569715eca 100644 --- a/packages/SystemUI/res-keyguard/values-az/strings.xml +++ b/packages/SystemUI/res-keyguard/values-az/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Cihaz yenidən başladıqdan sonra model tələb olunur"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Cihaz yeniden başladıqdan sonra PIN tələb olunur"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Cihaz yeniden başladıqdan sonra parol tələb olunur"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Əlavə təhlükəsizlik üçün model tələb olunur"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Əlavə təhlükəsizlik üçün PIN tələb olunur"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Əlavə təhlükəsizlik üçün parol tələb olunur"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Cihaz admin tərəfindən kilidlənib"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Cihaz əl ilə kilidləndi"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tanınmır"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Defolt"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Qabarcıq"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analoq"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml index 13d6613f0ff4..f0d1ef2d6bc3 100644 --- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Treba da unesete šablon kada se uređaj ponovo pokrene"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Treba da unesete PIN kada se uređaj ponovo pokrene"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Treba da unesete lozinku kada se uređaj ponovo pokrene"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Treba da unesete šablon radi dodatne bezbednosti"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Treba da unesete PIN radi dodatne bezbednosti"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Treba da unesete lozinku radi dodatne bezbednosti"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administrator je zaključao uređaj"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Uređaj je ručno zaključan"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nije prepoznat"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Podrazumevani"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Mehurići"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogni"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml index 616d31ac6bee..e1af3eceada8 100644 --- a/packages/SystemUI/res-keyguard/values-be/strings.xml +++ b/packages/SystemUI/res-keyguard/values-be/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Пасля перазапуску прылады патрабуецца ўзор"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Пасля перазапуску прылады патрабуецца PIN-код"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Пасля перазапуску прылады патрабуецца пароль"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Для забеспячэння дадатковай бяспекі патрабуецца ўзор"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Для забеспячэння дадатковай бяспекі патрабуецца PIN-код"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Для забеспячэння дадатковай бяспекі патрабуецца пароль"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Прылада заблакіравана адміністратарам"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Прылада была заблакіравана ўручную"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Не распазнана"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Стандартны"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Бурбалкі"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Са стрэлкамі"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml index 366a7f4cb817..0b4417ac30e8 100644 --- a/packages/SystemUI/res-keyguard/values-bg/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"След рестартиране на устройството се изисква фигура"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"След рестартиране на устройството се изисква ПИН код"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"След рестартиране на устройството се изисква парола"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"За допълнителна сигурност се изисква фигура"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"За допълнителна сигурност се изисква ПИН код"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"За допълнителна сигурност се изисква парола"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Устройството е заключено от администратора"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Устройството бе заключено ръчно"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Не е разпознато"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Стандартен"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Балонен"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Аналогов"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml index c20be5d70bc7..485157984749 100644 --- a/packages/SystemUI/res-keyguard/values-bn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ডিভাইসটি পুনরায় চালু হওয়ার পর প্যাটার্নের প্রয়োজন হবে"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ডিভাইসটি পুনরায় চালু হওয়ার পর পিন প্রয়োজন হবে"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ডিভাইসটি পুনরায় চালু হওয়ার পর পাসওয়ার্ডের প্রয়োজন হবে"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"অতিরিক্ত সুরক্ষার জন্য প্যাটার্ন দেওয়া প্রয়োজন"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"অতিরিক্ত সুরক্ষার জন্য পিন দেওয়া প্রয়োজন"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"অতিরিক্ত সুরক্ষার জন্য পাসওয়ার্ড দেওয়া প্রয়োজন"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"প্রশাসক ডিভাইসটি লক করেছেন"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ডিভাইসটিকে ম্যানুয়ালি লক করা হয়েছে"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"শনাক্ত করা যায়নি"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ডিফল্ট"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"বাবল"</string> <string name="clock_title_analog" msgid="8409262532900918273">"অ্যানালগ"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml index f1c00a91a734..4705b4d9645f 100644 --- a/packages/SystemUI/res-keyguard/values-bs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Potreban je uzorak nakon što se uređaj ponovo pokrene"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Potreban je PIN nakon što se uređaj ponovo pokrene"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Potrebna je lozinka nakon što se uređaj ponovo pokrene"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Uzorak je potreban radi dodatne sigurnosti"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN je potreban radi dodatne sigurnosti"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Lozinka je potrebna radi dodatne sigurnosti"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Uređaj je zaključao administrator"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Uređaj je ručno zaključan"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nije prepoznato"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Zadano"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Mjehurići"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogni"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml index 709407c128e0..284eaebfbd8e 100644 --- a/packages/SystemUI/res-keyguard/values-ca/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Cal introduir el patró quan es reinicia el dispositiu"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Cal introduir el PIN quan es reinicia el dispositiu"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Cal introduir la contrasenya quan es reinicia el dispositiu"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Cal introduir el patró per disposar de més seguretat"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Cal introduir el PIN per disposar de més seguretat"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Cal introduir la contrasenya per disposar de més seguretat"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"L\'administrador ha bloquejat el dispositiu"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositiu s\'ha bloquejat manualment"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"No s\'ha reconegut"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Predeterminada"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bombolla"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analògica"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml index a44658cc1de9..6b4f60742964 100644 --- a/packages/SystemUI/res-keyguard/values-cs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Po restartování zařízení je vyžadováno gesto"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Po restartování zařízení je vyžadován kód PIN"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Po restartování zařízení je vyžadováno heslo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pro ještě lepší zabezpečení je vyžadováno gesto"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Pro ještě lepší zabezpečení je vyžadován kód PIN"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Pro ještě lepší zabezpečení je vyžadováno heslo"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Zařízení je uzamknuto administrátorem"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Zařízení bylo ručně uzamčeno"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nerozpoznáno"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Výchozí"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bublina"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogové"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml index 331c35579c7b..85238dfdab0f 100644 --- a/packages/SystemUI/res-keyguard/values-da/strings.xml +++ b/packages/SystemUI/res-keyguard/values-da/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Du skal angive et mønster, når du har genstartet enheden"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Der skal angives en pinkode efter genstart af enheden"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Der skal angives en adgangskode efter genstart af enheden"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Der kræves et mønster som ekstra beskyttelse"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Der kræves en pinkode som ekstra beskyttelse"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Der kræves en adgangskode som ekstra beskyttelse"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Enheden er blevet låst af administratoren"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Enheden blev låst manuelt"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ikke genkendt"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Standard"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Boble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml index c19b357b5985..18befed429a9 100644 --- a/packages/SystemUI/res-keyguard/values-de/strings.xml +++ b/packages/SystemUI/res-keyguard/values-de/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Nach dem Neustart des Geräts ist die Eingabe des Musters erforderlich"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Nach dem Neustart des Geräts ist die Eingabe der PIN erforderlich"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Nach dem Neustart des Geräts ist die Eingabe des Passworts erforderlich"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Zur Verbesserung der Sicherheit ist ein Muster erforderlich"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Zur Verbesserung der Sicherheit ist eine PIN erforderlich"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Zur Verbesserung der Sicherheit ist ein Passwort erforderlich"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Gerät vom Administrator gesperrt"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Gerät manuell gesperrt"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nicht erkannt"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Standard"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml index 1d6ec8240a9f..65b844862a9f 100644 --- a/packages/SystemUI/res-keyguard/values-el/strings.xml +++ b/packages/SystemUI/res-keyguard/values-el/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Απαιτείται μοτίβο μετά από την επανεκκίνηση της συσκευής"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Απαιτείται PIN μετά από την επανεκκίνηση της συσκευής"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Απαιτείται κωδικός πρόσβασης μετά από την επανεκκίνηση της συσκευής"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Απαιτείται μοτίβο για πρόσθετη ασφάλεια"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Απαιτείται PIN για πρόσθετη ασφάλεια"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Απαιτείται κωδικός πρόσβασης για πρόσθετη ασφάλεια"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Η συσκευή κλειδώθηκε από τον διαχειριστή"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Η συσκευή κλειδώθηκε με μη αυτόματο τρόπο"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Δεν αναγνωρίστηκε"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Προεπιλογή"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Συννεφάκι"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Αναλογικό"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml index 2b78f9678415..588f1b501f53 100644 --- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN required after device restarts"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Password required after device restarts"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogue"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml index e1c253202c60..08fc8d66c98d 100644 --- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN required after device restarts"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Password required after device restarts"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogue"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml index 2b78f9678415..588f1b501f53 100644 --- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN required after device restarts"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Password required after device restarts"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogue"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml index 2b78f9678415..588f1b501f53 100644 --- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN required after device restarts"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Password required after device restarts"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogue"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml index 9052e4f04e54..a23aeb0822f3 100644 --- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN required after device restarts"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Password required after device restarts"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"For additional security, use pattern instead"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"For additional security, use PIN instead"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"For additional security, use password instead"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognized"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Unlock your device to continue"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml index 9dc054a53393..c71a67865925 100644 --- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Se requiere el patrón después de reiniciar el dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Se requiere el PIN después de reiniciar el dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Se requiere la contraseña después de reiniciar el dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Se requiere el patrón por razones de seguridad"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Se requiere el PIN por razones de seguridad"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Se requiere la contraseña por razones de seguridad"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado por el administrador"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositivo se bloqueó de forma manual"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"No se reconoció"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Predeterminado"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Burbuja"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml index f9f0452771af..c6ee6980ff3b 100644 --- a/packages/SystemUI/res-keyguard/values-es/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Debes introducir el patrón después de reiniciar el dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Debes introducir el PIN después de reiniciar el dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Debes introducir la contraseña después de reiniciar el dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Debes introducir el patrón como medida de seguridad adicional"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Debes introducir el PIN como medida de seguridad adicional"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Debes introducir la contraseña como medida de seguridad adicional"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado por el administrador"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositivo se ha bloqueado manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"No se reconoce"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Predeterminado"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Burbuja"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml index dceb78efaca7..071ede8a0b25 100644 --- a/packages/SystemUI/res-keyguard/values-et/strings.xml +++ b/packages/SystemUI/res-keyguard/values-et/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pärast seadme taaskäivitamist tuleb sisestada muster"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Pärast seadme taaskäivitamist tuleb sisestada PIN-kood"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Pärast seadme taaskäivitamist tuleb sisestada parool"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Lisaturvalisuse huvides tuleb sisestada muster"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Lisaturvalisuse huvides tuleb sisestada PIN-kood"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Lisaturvalisuse huvides tuleb sisestada parool"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administraator lukustas seadme"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Seade lukustati käsitsi"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ei tuvastatud"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Vaikenumbrilaud"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Mull"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analoog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml index 8431268464eb..9b8e65b1dde7 100644 --- a/packages/SystemUI/res-keyguard/values-eu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Eredua marraztu beharko duzu gailua berrabiarazten denean"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PINa idatzi beharko duzu gailua berrabiarazten denean"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Pasahitza idatzi beharko duzu gailua berrabiarazten denean"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Eredua behar da gailua babestuago izateko"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PINa behar da gailua babestuago izateko"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Pasahitza behar da gailua babestuago izateko"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administratzaileak blokeatu egin du gailua"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Eskuz blokeatu da gailua"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ez da ezagutu"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Lehenetsia"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Puxikak"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogikoa"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml index 37bb260b28d3..3583f1e60e7a 100644 --- a/packages/SystemUI/res-keyguard/values-fa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"بعد از بازنشانی دستگاه باید الگو وارد شود"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"بعد از بازنشانی دستگاه باید پین وارد شود"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"بعد از بازنشانی دستگاه باید گذرواژه وارد شود"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"برای ایمنی بیشتر باید الگو وارد شود"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"برای ایمنی بیشتر باید پین وارد شود"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"برای ایمنی بیشتر باید گذرواژه وارد شود"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"دستگاه توسط سرپرست سیستم قفل شده است"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"دستگاه بهصورت دستی قفل شده است"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"شناسایی نشد"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"پیشفرض"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"حباب"</string> <string name="clock_title_analog" msgid="8409262532900918273">"آنالوگ"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml index f8cec421844c..a0ac6df2f029 100644 --- a/packages/SystemUI/res-keyguard/values-fi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Kuvio vaaditaan laitteen uudelleenkäynnistyksen jälkeen."</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN-koodi vaaditaan laitteen uudelleenkäynnistyksen jälkeen."</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Salasana vaaditaan laitteen uudelleenkäynnistyksen jälkeen."</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Kuvio vaaditaan suojauksen parantamiseksi."</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN-koodi vaaditaan suojauksen parantamiseksi."</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Salasana vaaditaan suojauksen parantamiseksi."</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Järjestelmänvalvoja lukitsi laitteen."</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Laite lukittiin manuaalisesti"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ei tunnistettu"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Oletus"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Kupla"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analoginen"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml index 077fe11be4f2..66fd7c08f0e2 100644 --- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Le schéma est exigé après le redémarrage de l\'appareil"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Le NIP est exigé après le redémarrage de l\'appareil"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Le mot de passe est exigé après le redémarrage de l\'appareil"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Le schéma est exigé pour plus de sécurité"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Le NIP est exigé pour plus de sécurité"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Le mot de passe est exigé pour plus de sécurité"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Pour plus de sécurité, utilisez plutôt un schéma"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Pour plus de sécurité, utilisez plutôt un NIP"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Pour plus de sécurité, utilisez plutôt un mot de passe"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"L\'appareil a été verrouillé par l\'administrateur"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"L\'appareil a été verrouillé manuellement"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Doigt non reconnu"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Par défaut"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bulle"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogique"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Déverrouiller votre appareil pour continuer"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml index 45dadc1dfdc4..ec00ba3ae887 100644 --- a/packages/SystemUI/res-keyguard/values-fr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Veuillez dessiner le schéma après le redémarrage de l\'appareil"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Veuillez saisir le code après le redémarrage de l\'appareil"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Veuillez saisir le mot de passe après le redémarrage de l\'appareil"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Veuillez dessiner le schéma pour renforcer la sécurité"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Veuillez saisir le code pour renforcer la sécurité"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Veuillez saisir le mot de passe pour renforcer la sécurité"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Appareil verrouillé par l\'administrateur"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Appareil verrouillé manuellement"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non reconnu"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Par défaut"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bulle"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogique"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml index 4fbdd676d23a..a3f8e86cd5e6 100644 --- a/packages/SystemUI/res-keyguard/values-gl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"É necesario o padrón despois do reinicio do dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"É necesario o PIN despois do reinicio do dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"É necesario o contrasinal despois do reinicio do dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"É necesario o padrón para obter seguranza adicional"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"É necesario o PIN para obter seguranza adicional"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"É necesario o contrasinal para obter seguranza adicional"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"O administrador bloqueou o dispositivo"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo bloqueouse manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non se recoñeceu"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Predeterminado"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Burbulla"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analóxico"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml index 6caac8a89a66..c97fe017ec60 100644 --- a/packages/SystemUI/res-keyguard/values-gu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ઉપકરણનો પુનઃપ્રારંભ થાય તે પછી પૅટર્ન જરૂરી છે"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ઉપકરણનો પુનઃપ્રારંભ થાય તે પછી પિન જરૂરી છે"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ઉપકરણનો પુનઃપ્રારંભ થાય તે પછી પાસવર્ડ જરૂરી છે"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"વધારાની સુરક્ષા માટે પૅટર્ન જરૂરી છે"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"વધારાની સુરક્ષા માટે પિન જરૂરી છે"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"વધારાની સુરક્ષા માટે પાસવર્ડ જરૂરી છે"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"વ્યવસ્થાપકે ઉપકરણ લૉક કરેલું છે"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ઉપકરણ મેન્યુઅલી લૉક કર્યું હતું"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"ઓળખાયેલ નથી"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ડિફૉલ્ટ"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"બબલ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"એનાલોગ"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml index 627576e1af66..128300488f27 100644 --- a/packages/SystemUI/res-keyguard/values-hi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"डिवाइस फिर से चालू होने के बाद पैटर्न ज़रूरी है"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"डिवाइस फिर से चालू होने के बाद पिन ज़रूरी है"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"डिवाइस फिर से चालू होने के बाद पासवर्ड ज़रूरी है"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"अतिरिक्त सुरक्षा के लिए पैटर्न ज़रूरी है"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"अतिरिक्त सुरक्षा के लिए पिन ज़रूरी है"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"अतिरिक्त सुरक्षा के लिए पासवर्ड ज़रूरी है"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"व्यवस्थापक ने डिवाइस को लॉक किया है"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"डिवाइस को मैन्युअल रूप से लॉक किया गया था"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"पहचान नहीं हो पाई"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"डिफ़ॉल्ट"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"बबल"</string> <string name="clock_title_analog" msgid="8409262532900918273">"एनालॉग"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml index 8b1b5042f7f6..7a14a80e9bb3 100644 --- a/packages/SystemUI/res-keyguard/values-hr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Nakon ponovnog pokretanja uređaja morate unijeti uzorak"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Nakon ponovnog pokretanja uređaja morate unijeti PIN"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Nakon ponovnog pokretanja uređaja morate unijeti zaporku"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Unesite uzorak radi dodatne sigurnosti"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Unesite PIN radi dodatne sigurnosti"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Unesite zaporku radi dodatne sigurnosti"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administrator je zaključao uređaj"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Uređaj je ručno zaključan"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nije prepoznato"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Zadano"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Mjehurić"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogni"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml index 6b75e722dbfc..a4fbf537d331 100644 --- a/packages/SystemUI/res-keyguard/values-hu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Az eszköz újraindítását követően meg kell adni a mintát"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Az eszköz újraindítását követően meg kell adni a PIN-kódot"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Az eszköz újraindítását követően meg kell adni a jelszót"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"A nagyobb biztonság érdekében minta szükséges"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"A nagyobb biztonság érdekében PIN-kód szükséges"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"A nagyobb biztonság érdekében jelszó szükséges"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"A rendszergazda zárolta az eszközt"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Az eszközt manuálisan lezárták"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nem ismerhető fel"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Alapértelmezett"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Buborék"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analóg"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml index 3412026b90f3..086eeb939941 100644 --- a/packages/SystemUI/res-keyguard/values-hy/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Սարքը վերագործարկելուց հետո անհրաժեշտ է մուտքագրել նախշը"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Սարքը վերագործարկելուց հետո անհրաժեշտ է մուտքագրել PIN կոդը"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Սարքը վերագործարկելուց հետո անհրաժեշտ է մուտքագրել գաղտնաբառը"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Անվտանգության նկատառումներից ելնելով անհրաժեշտ է մուտքագրել նախշը"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Անվտանգության նկատառումներից ելնելով անհրաժեշտ է մուտքագրել PIN կոդը"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Անվտանգության նկատառումներից ելնելով անհրաժեշտ է մուտքագրել գաղտնաբառը"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Սարքը կողպված է ադմինիստրատորի կողմից"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Սարքը կողպվել է ձեռքով"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Չհաջողվեց ճանաչել"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Կանխադրված"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Պղպջակ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Անալոգային"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml index 1afb7918dd83..b43a0322fc7a 100644 --- a/packages/SystemUI/res-keyguard/values-in/strings.xml +++ b/packages/SystemUI/res-keyguard/values-in/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pola diperlukan setelah perangkat dimulai ulang"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN diperlukan setelah perangkat dimulai ulang"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Sandi diperlukan setelah perangkat dimulai ulang"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pola diperlukan untuk keamanan tambahan"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN diperlukan untuk keamanan tambahan"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Sandi diperlukan untuk keamanan tambahan"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Perangkat dikunci oleh admin"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Perangkat dikunci secara manual"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tidak dikenali"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Balon"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml index 6abdc82ceecd..8bad961dae4b 100644 --- a/packages/SystemUI/res-keyguard/values-is/strings.xml +++ b/packages/SystemUI/res-keyguard/values-is/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Mynsturs er krafist þegar tækið er endurræst"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN-númers er krafist þegar tækið er endurræst"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Aðgangsorðs er krafist þegar tækið er endurræst"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Mynsturs er krafist af öryggisástæðum"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN-númers er krafist af öryggisástæðum"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Aðgangsorðs er krafist af öryggisástæðum"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Kerfisstjóri læsti tæki"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Tækinu var læst handvirkt"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Þekktist ekki"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Sjálfgefið"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Blaðra"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Með vísum"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index 9fed5f72afa1..186177ff6d49 100644 --- a/packages/SystemUI/res-keyguard/values-it/strings.xml +++ b/packages/SystemUI/res-keyguard/values-it/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Sequenza obbligatoria dopo il riavvio del dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN obbligatorio dopo il riavvio del dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Password obbligatoria dopo il riavvio del dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Sequenza obbligatoria per maggiore sicurezza"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN obbligatorio per maggiore sicurezza"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password obbligatoria per maggiore sicurezza"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloccato dall\'amministratore"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Il dispositivo è stato bloccato manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non riconosciuto"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Predefinito"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bolla"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogico"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml index b5b1c533778b..aab42069590b 100644 --- a/packages/SystemUI/res-keyguard/values-iw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"יש להזין את קו ביטול הנעילה לאחר הפעלה מחדש של המכשיר"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"צריך להזין קוד אימות לאחר הפעלה מחדש של המכשיר"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"יש להזין סיסמה לאחר הפעלה מחדש של המכשיר"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"יש להזין את קו ביטול הנעילה כדי להגביר את רמת האבטחה"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"יש להזין קוד אימות כדי להגביר את רמת האבטחה"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"יש להזין סיסמה כדי להגביר את רמת האבטחה"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"כדי להגביר את רמת האבטחה, כדאי להשתמש בקו ביטול נעילה במקום זאת"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"כדי להגביר את רמת האבטחה, כדאי להשתמש בקוד אימות במקום זאת"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"כדי להגביר את רמת האבטחה, כדאי להשתמש בסיסמה במקום זאת"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"המנהל של המכשיר נהל אותו"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"המכשיר ננעל באופן ידני"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"לא זוהתה"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"ברירת מחדל"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"בועה"</string> <string name="clock_title_analog" msgid="8409262532900918273">"אנלוגי"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"צריך לבטל את הנעילה של המכשיר כדי להמשיך"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml index afe0159ca1d6..1a4fb0b8e243 100644 --- a/packages/SystemUI/res-keyguard/values-ja/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"デバイスの再起動後はパターンの入力が必要となります"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"デバイスの再起動後は PIN の入力が必要となります"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"デバイスの再起動後はパスワードの入力が必要となります"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"追加の確認のためパターンが必要です"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"追加の確認のため PIN が必要です"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"追加の確認のためパスワードが必要です"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"セキュリティを強化するには代わりにパターンを使用してください"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"セキュリティを強化するには代わりに PIN を使用してください"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"セキュリティを強化するには代わりにパスワードを使用してください"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"デバイスは管理者によりロックされています"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"デバイスは手動でロックされました"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"認識されませんでした"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"デフォルト"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"バブル"</string> <string name="clock_title_analog" msgid="8409262532900918273">"アナログ"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"続行するにはデバイスのロックを解除してください"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml index b32caa75f453..123cc39e47da 100644 --- a/packages/SystemUI/res-keyguard/values-ka/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"მოწყობილობის გადატვირთვის შემდეგ საჭიროა ნიმუშის დახატვა"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"მოწყობილობის გადატვირთვის შემდეგ საჭიროა PIN-კოდის შეყვანა"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"მოწყობილობის გადატვირთვის შემდეგ საჭიროა პაროლის შეყვანა"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"დამატებითი უსაფრთხოებისთვის საჭიროა ნიმუშის დახატვა"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"დამატებითი უსაფრთხოებისთვის საჭიროა PIN-კოდის შეყვანა"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"დამატებითი უსაფრთხოებისთვის საჭიროა პაროლის შეყვანა"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"მოწყობილობა ჩაკეტილია ადმინისტრატორის მიერ"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"მოწყობილობა ხელით ჩაიკეტა"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"არ არის ამოცნობილი"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ნაგულისხმევი"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"ბუშტი"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ანალოგური"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml index d6d5bcdd4beb..8daca5c6d59a 100644 --- a/packages/SystemUI/res-keyguard/values-kk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Құрылғы қайта іске қосылғаннан кейін, өрнекті енгізу қажет"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Құрылғы қайта іске қосылғаннан кейін, PIN кодын енгізу қажет"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Құрылғы қайта іске қосылғаннан кейін, құпия сөзді енгізу қажет"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Қауіпсіздікті күшейту үшін өрнекті енгізу қажет"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Қауіпсіздікті күшейту үшін PIN кодын енгізу қажет"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Қауіпсіздікті күшейту үшін құпия сөзді енгізу қажет"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Құрылғыны әкімші құлыптаған"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Құрылғы қолмен құлыпталды"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Танылмады"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Әдепкі"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Көпіршік"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Аналогтық"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml index 00bfe05ada14..73f507c91ece 100644 --- a/packages/SystemUI/res-keyguard/values-km/strings.xml +++ b/packages/SystemUI/res-keyguard/values-km/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"តម្រូវឲ្យប្រើលំនាំ បន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"តម្រូវឲ្យបញ្ចូលកូដ PIN បន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"តម្រូវឲ្យបញ្ចូលពាក្យសម្ងាត់ បន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"តម្រូវឲ្យប្រើលំនាំ ដើម្បីទទួលបានសវុត្ថិភាពបន្ថែម"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"តម្រូវឲ្យបញ្ចូលកូដ PIN ដើម្បីទទួលបានសុវត្ថិភាពបន្ថែម"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"តម្រូវឲ្យបញ្ចូលពាក្យសម្ងាត់ ដើម្បីទទួលបានសុវត្ថិភាពបន្ថែម"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ឧបករណ៍ត្រូវបានចាក់សោដោយអ្នកគ្រប់គ្រង"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ឧបករណ៍ត្រូវបានចាក់សោដោយអ្នកប្រើផ្ទាល់"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"មិនអាចសម្គាល់បានទេ"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"លំនាំដើម"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"ពពុះ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"អាណាឡូក"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml index 80a98e6ff6d7..c279ceac244e 100644 --- a/packages/SystemUI/res-keyguard/values-kn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ಸಾಧನ ಮರುಪ್ರಾರಂಭಗೊಂಡ ನಂತರ ಪ್ಯಾಟರ್ನ್ ಅಗತ್ಯವಿರುತ್ತದೆ"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ಸಾಧನ ಮರುಪ್ರಾರಂಭಗೊಂಡ ನಂತರ ಪಿನ್ ಅಗತ್ಯವಿರುತ್ತದೆ"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ಸಾಧನ ಮರುಪ್ರಾರಂಭಗೊಂಡ ನಂತರ ಪಾಸ್ವರ್ಡ್ ಅಗತ್ಯವಿರುತ್ತದೆ"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಗೆ ಪ್ಯಾಟರ್ನ್ ಅಗತ್ಯವಿದೆ"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಗೆ ಪಿನ್ ಅಗತ್ಯವಿದೆ"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಗಾಗಿ ಪಾಸ್ವರ್ಡ್ ಅಗತ್ಯವಿದೆ"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ನಿರ್ವಾಹಕರು ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಿದ್ದಾರೆ"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ಸಾಧನವನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ಡೀಫಾಲ್ಟ್"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"ಬಬಲ್"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ಅನಲಾಗ್"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml index b952f1bba2dd..4c058edbf688 100644 --- a/packages/SystemUI/res-keyguard/values-ko/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"기기가 다시 시작되면 패턴이 필요합니다."</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"기기가 다시 시작되면 PIN이 필요합니다."</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"기기가 다시 시작되면 비밀번호가 필요합니다."</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"보안 강화를 위해 패턴이 필요합니다."</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"보안 강화를 위해 PIN이 필요합니다."</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"보안 강화를 위해 비밀번호가 필요합니다."</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"관리자가 기기를 잠갔습니다."</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"기기가 수동으로 잠금 설정되었습니다."</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"인식할 수 없음"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"기본"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"버블"</string> <string name="clock_title_analog" msgid="8409262532900918273">"아날로그"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml index 485337d86408..7c7099e1cf61 100644 --- a/packages/SystemUI/res-keyguard/values-ky/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Түзмөк кайра күйгүзүлгөндөн кийин графикалык ачкычты тартуу талап кылынат"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Түзмөк кайра күйгүзүлгөндөн кийин PIN-кодду киргизүү талап кылынат"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Түзмөк кайра күйгүзүлгөндөн кийин сырсөздү киргизүү талап кылынат"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Коопсуздукту бекемдөө үчүн графикалык ачкыч талап кылынат"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Коопсуздукту бекемдөө үчүн PIN-код талап кылынат"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Коопсуздукту бекемдөө үчүн сырсөз талап кылынат"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Түзмөктү администратор кулпулап койгон"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Түзмөк кол менен кулпуланды"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Таанылган жок"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Демейки"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Көбүк"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Аналог"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml index 17584b5a74fe..5a6df42884b4 100644 --- a/packages/SystemUI/res-keyguard/values-lo/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ຈຳເປັນຕ້ອງມີແບບຮູບປົດລັອກຫຼັງຈາກອຸປະກອນເລີ່ມລະບົບໃໝ່"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ຈຳເປັນຕ້ອງມີ PIN ຫຼັງຈາກອຸປະກອນເລີ່ມລະບົບໃໝ່"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ຈຳເປັນຕ້ອງມີລະຫັດຜ່ານຫຼັງຈາກອຸປະກອນເລີ່ມລະບົບໃໝ່"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ຈຳເປັນຕ້ອງມີແບບຮູບເພື່ອຄວາມປອດໄພເພີ່ມເຕີມ"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ຈຳເປັນຕ້ອງມີ PIN ເພື່ອຄວາມປອດໄພເພີ່ມເຕີມ"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ຈຳເປັນຕ້ອງມີລະຫັດຜ່ານເພື່ອຄວາມປອດໄພເພີ່ມເຕີມ"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ອຸປະກອນຖືກລັອກໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ອຸປະກອນຖືກສັ່ງໃຫ້ລັອກ"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"ບໍ່ຮູ້ຈັກ"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ຄ່າເລີ່ມຕົ້ນ"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"ຟອງ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ໂມງເຂັມ"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml index a066a66ec6a4..4d98fd17baf8 100644 --- a/packages/SystemUI/res-keyguard/values-lt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Iš naujo paleidus įrenginį būtinas atrakinimo piešinys"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Iš naujo paleidus įrenginį būtinas PIN kodas"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Iš naujo paleidus įrenginį būtinas slaptažodis"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Norint užtikrinti papildomą saugą būtinas atrakinimo piešinys"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Norint užtikrinti papildomą saugą būtinas PIN kodas"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Norint užtikrinti papildomą saugą būtinas slaptažodis"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Įrenginį užrakino administratorius"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Įrenginys užrakintas neautomatiškai"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Neatpažinta"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Numatytasis"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Debesėlis"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analoginis"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml index d371a4b9cbab..2660a069c949 100644 --- a/packages/SystemUI/res-keyguard/values-lv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pēc ierīces restartēšanas ir jāievada atbloķēšanas kombinācija."</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Pēc ierīces restartēšanas ir jāievada PIN kods."</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Pēc ierīces restartēšanas ir jāievada parole."</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Papildu drošībai ir jāievada atbloķēšanas kombinācija."</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Papildu drošībai ir jāievada PIN kods."</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Papildu drošībai ir jāievada parole."</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administrators bloķēja ierīci."</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Ierīce tika bloķēta manuāli."</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nav atpazīts"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Noklusējums"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Burbuļi"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogais"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml index ef22564318e8..77e1b50d7a79 100644 --- a/packages/SystemUI/res-keyguard/values-mk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Потребна е шема по рестартирање на уредот"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Потребен е PIN-код по рестартирање на уредот"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Потребна е лозинка по рестартирање на уредот"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Потребна е шема за дополнителна безбедност"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Потребен е PIN-код за дополнителна безбедност"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Потребна е лозинка за дополнителна безбедност"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"За дополнителна безбедност, користете шема"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"За дополнителна безбедност, користете PIN"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"За дополнителна безбедност, користете лозинка"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Уредот е заклучен од администраторот"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Уредот е заклучен рачно"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Непознат"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Стандарден"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Балонче"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Аналоген"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Отклучете го уредот за да продолжите"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml index 63a542a63e04..e62b4356822d 100644 --- a/packages/SystemUI/res-keyguard/values-ml/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ഉപകരണം റീസ്റ്റാർട്ടായശേഷം പാറ്റേൺ വരയ്ക്കേണ്ടതുണ്ട്"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ഉപകരണം റീസ്റ്റാർട്ടായശേഷം പിൻ നൽകേണ്ടതുണ്ട്"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ഉപകരണം റീസ്റ്റാർട്ടായശേഷം പാസ്വേഡ് നൽകേണ്ടതുണ്ട്"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"അധിക സുരക്ഷയ്ക്ക് പാറ്റേൺ ആവശ്യമാണ്"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"അധിക സുരക്ഷയ്ക്ക് പിൻ ആവശ്യമാണ്"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"അധിക സുരക്ഷയ്ക്ക് പാസ്വേഡ് ആവശ്യമാണ്"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ഉപകരണം അഡ്മിൻ ലോക്കുചെയ്തു"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ഉപകരണം നേരിട്ട് ലോക്കുചെയ്തു"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"തിരിച്ചറിയുന്നില്ല"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ഡിഫോൾട്ട്"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"ബബിൾ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"അനലോഗ്"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml index 71c913f988bd..f2cc5ab195a0 100644 --- a/packages/SystemUI/res-keyguard/values-mn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Төхөөрөмжийг дахин эхлүүлсний дараа загвар оруулах шаардлагатай"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Төхөөрөмжийг дахин эхлүүлсний дараа ПИН оруулах шаардлагатай"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Төхөөрөмжийг дахин эхлүүлсний дараа нууц үг оруулах шаардлагатай"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Аюулгүй байдлын үүднээс загвар оруулах шаардлагатай"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Аюулгүй байдлын үүднээс ПИН оруулах шаардлагатай"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Аюулгүй байдлын үүднээс нууц үг оруулах шаардлагатай"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Нэмэлт аюулгүй байдлын үүднээс оронд нь хээ ашиглана уу"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Нэмэлт аюулгүй байдлын үүднээс оронд нь ПИН ашиглана уу"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Нэмэлт аюулгүй байдлын үүднээс оронд нь нууц үг ашиглана уу"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Админ төхөөрөмжийг түгжсэн"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Төхөөрөмжийг гараар түгжсэн"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Таньж чадсангүй"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Өгөгдмөл"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Бөмбөлөг"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Aналог"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Үргэлжлүүлэхийн тулд төхөөрөмжийнхөө түгжээг тайлна уу"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml index 6ac13bdde13a..1454b20d3797 100644 --- a/packages/SystemUI/res-keyguard/values-mr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"डिव्हाइस रीस्टार्ट झाल्यावर पॅटर्न आवश्यक आहे"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"डिव्हाइस रीस्टार्ट झाल्यावर पिन आवश्यक आहे"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"डिव्हाइस रीस्टार्ट झाल्यावर पासवर्ड आवश्यक आहे"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"अतिरिक्त सुरक्षिततेसाठी पॅटर्न आवश्यक आहे"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"अतिरिक्त सुरक्षिततेसाठी पिन आवश्यक आहे"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"अतिरिक्त सुरक्षिततेसाठी पासवर्ड आवश्यक आहे"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"प्रशासकाद्वारे लॉक केलेले डिव्हाइस"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"डिव्हाइस मॅन्युअली लॉक केले होते"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"ओळखले नाही"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"डीफॉल्ट"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"बबल"</string> <string name="clock_title_analog" msgid="8409262532900918273">"अॅनालॉग"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml index 453afc3d6b37..a6d1af9368ec 100644 --- a/packages/SystemUI/res-keyguard/values-ms/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Corak diperlukan setelah peranti dimulakan semula"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"PIN diperlukan setelah peranti dimulakan semula"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Kata laluan diperlukan setelah peranti dimulakan semula"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Corak diperlukan untuk keselamatan tambahan"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN diperlukan untuk keselamatan tambahan"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Kata laluan diperlukan untuk keselamatan tambahan"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Peranti dikunci oleh pentadbir"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Peranti telah dikunci secara manual"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tidak dikenali"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Lalai"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Gelembung"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml index 1cc46b16ec3f..5617a1188a40 100644 --- a/packages/SystemUI/res-keyguard/values-my/strings.xml +++ b/packages/SystemUI/res-keyguard/values-my/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"စက်ပစ္စည်းကို ပိတ်ပြီးပြန်ဖွင့်လိုက်သည့်အခါတွင် ပုံစံ လိုအပ်ပါသည်"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"စက်ပစ္စည်းကို ပိတ်ပြီးပြန်ဖွင့်လိုက်သည့်အခါတွင် ပင်နံပါတ် လိုအပ်ပါသည်"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"စက်ပစ္စည်းကို ပိတ်ပြီးပြန်ဖွင့်လိုက်သည့်အခါတွင် စကားဝှက် လိုအပ်ပါသည်"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ပိုမို၍ လုံခြုံမှု ရှိစေရန် ပုံစံ လိုအပ်ပါသည်"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ပိုမို၍ လုံခြုံမှု ရှိစေရန် ပင်နံပါတ် လိုအပ်ပါသည်"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ပိုမို၍ လုံခြုံမှု ရှိစေရန် စကားဝှက် လိုအပ်ပါသည်"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"စက်ပစ္စည်းကို စီမံခန့်ခွဲသူက လော့ခ်ချထားပါသည်"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"စက်ပစ္စည်းကို ကိုယ်တိုင်ကိုယ်ကျ လော့ခ်ချထားခဲ့သည်"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"မသိ"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"မူလ"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"ပူဖောင်းကွက်"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ရိုးရိုး"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml index 5310a7301d4e..0ad9e951b1e4 100644 --- a/packages/SystemUI/res-keyguard/values-nb/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Du må tegne mønsteret etter at enheten har startet på nytt"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Du må skrive inn PIN-koden etter at enheten har startet på nytt"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Du må skrive inn passordet etter at enheten har startet på nytt"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Du må tegne mønsteret for ekstra sikkerhet"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Du må skrive inn PIN-koden for ekstra sikkerhet"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Du må skrive inn passordet for ekstra sikkerhet"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Enheten er låst av administratoren"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Enheten ble låst manuelt"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ikke gjenkjent"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Standard"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Boble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml index 534164b3f2c9..196b74a5658b 100644 --- a/packages/SystemUI/res-keyguard/values-ne/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"यन्त्र पुनः सुरु भएपछि ढाँचा आवश्यक पर्दछ"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"यन्त्र पुनः सुरु भएपछि PIN आवश्यक पर्दछ"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"यन्त्र पुनः सुरु भएपछि पासवर्ड आवश्यक पर्दछ"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"अतिरिक्त सुरक्षाको लागि ढाँचा आवश्यक छ"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"अतिरिक्त सुरक्षाको लागि PIN आवश्यक छ"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"अतिरिक्त सुरक्षाको लागि पासवर्ड आवश्यक छ"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"प्रशासकले यन्त्रलाई लक गर्नुभएको छ"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"यन्त्रलाई म्यानुअल तरिकाले लक गरिएको थियो"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"पहिचान भएन"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"डिफल्ट"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"बबल"</string> <string name="clock_title_analog" msgid="8409262532900918273">"एनालग"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml index 08e226d4ec07..747b3bbd9128 100644 --- a/packages/SystemUI/res-keyguard/values-nl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Patroon vereist nadat het apparaat opnieuw is opgestart"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Pincode vereist nadat het apparaat opnieuw is opgestart"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Wachtwoord vereist nadat het apparaat opnieuw is opgestart"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Patroon vereist voor extra beveiliging"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Pincode vereist voor extra beveiliging"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Wachtwoord vereist voor extra beveiliging"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Apparaat vergrendeld door beheerder"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Apparaat is handmatig vergrendeld"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Niet herkend"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Standaard"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bel"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analoog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml index 3cdd2649d1b4..75f7a898585b 100644 --- a/packages/SystemUI/res-keyguard/values-or/strings.xml +++ b/packages/SystemUI/res-keyguard/values-or/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ଡିଭାଇସ୍ ରିଷ୍ଟାର୍ଟ ହେବା ପରେ ପାଟର୍ନ ଆବଶ୍ୟକ ଅଟେ"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ଡିଭାଇସ୍ ରିଷ୍ଟାର୍ଟ ହେବାପରେ ପାସ୍ୱର୍ଡ ଆବଶ୍ୟକ"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ଡିଭାଇସ୍ ରିଷ୍ଟାର୍ଟ ହେବା ପରେ ପାସୱର୍ଡ ଆବଶ୍ୟକ ଅଟେ"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ ପାଟର୍ନ ଆବଶ୍ୟକ"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ PIN ଆବଶ୍ୟକ ଅଟେ"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ ପାସ୍ୱର୍ଡ ଆବଶ୍ୟକ"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ, ଏହା ପରିବର୍ତ୍ତେ ପାଟର୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ, ଏହା ପରିବର୍ତ୍ତେ PIN ବ୍ୟବହାର କରନ୍ତୁ"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ, ଏହା ପରିବର୍ତ୍ତେ ପାସୱାର୍ଡ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ଡିଭାଇସ୍ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଲକ୍ କରାଯାଇଛି"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ଡିଭାଇସ୍ ମାନୁଆଲ ଭାବେ ଲକ୍ କରାଗଲା"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"ଡିଫଲ୍ଟ"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"ବବଲ୍"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ଆନାଲଗ୍"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"ଜାରି ରଖିବା ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ କରନ୍ତୁ"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml index 409f72740649..bf1a359a2c75 100644 --- a/packages/SystemUI/res-keyguard/values-pa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ ਪਿੰਨ ਦੀ ਲੋੜ ਹੈ"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪਿੰਨ ਦੀ ਲੋੜ ਹੈ"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਡੀਵਾਈਸ ਨੂੰ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ਡੀਵਾਈਸ ਨੂੰ ਹੱਥੀਂ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ਪੂਰਵ-ਨਿਰਧਾਰਿਤ"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"ਬੁਲਬੁਲਾ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ਐਨਾਲੌਗ"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml index 52bc98236330..c49149baa93a 100644 --- a/packages/SystemUI/res-keyguard/values-pl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Po ponownym uruchomieniu urządzenia wymagany jest wzór"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Po ponownym uruchomieniu urządzenia wymagany jest kod PIN"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Po ponownym uruchomieniu urządzenia wymagane jest hasło"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Dla większego bezpieczeństwa musisz narysować wzór"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Dla większego bezpieczeństwa musisz podać kod PIN"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Dla większego bezpieczeństwa musisz podać hasło"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Urządzenie zablokowane przez administratora"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Urządzenie zostało zablokowane ręcznie"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nie rozpoznano"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Domyślna"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bąbelkowy"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogowy"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml index b9348260d40e..3d60e8c45bcb 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"O padrão é exigido após a reinicialização do dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"O PIN é exigido após a reinicialização do dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"A senha é exigida após a reinicialização do dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"O padrão é necessário para aumentar a segurança"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"O PIN é necessário para aumentar a segurança"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"A senha é necessária para aumentar a segurança"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para ter mais segurança, use o padrão"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para ter mais segurança, use o PIN"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para ter mais segurança, use a senha"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado pelo administrador"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Padrão"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bolha"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Desbloqueie o dispositivo para continuar"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index a67bfb020a3c..0a943496fba9 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"É necessário um padrão após reiniciar o dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"É necessário um PIN após reiniciar o dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"É necessária uma palavra-passe após reiniciar o dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Para segurança adicional, é necessário um padrão"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Para segurança adicional, é necessário um PIN"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Para segurança adicional, é necessária uma palavra-passe"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para uma segurança adicional, use antes o padrão"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para uma segurança adicional, use antes o PIN"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para uma segurança adicional, use antes a palavra-passe"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado pelo gestor"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido."</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Predefinido"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Balão"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Desbloqueie o dispositivo para continuar"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml index b9348260d40e..3d60e8c45bcb 100644 --- a/packages/SystemUI/res-keyguard/values-pt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"O padrão é exigido após a reinicialização do dispositivo"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"O PIN é exigido após a reinicialização do dispositivo"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"A senha é exigida após a reinicialização do dispositivo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"O padrão é necessário para aumentar a segurança"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"O PIN é necessário para aumentar a segurança"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"A senha é necessária para aumentar a segurança"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para ter mais segurança, use o padrão"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para ter mais segurança, use o PIN"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para ter mais segurança, use a senha"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado pelo administrador"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Padrão"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bolha"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Desbloqueie o dispositivo para continuar"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml index 5ee67d917768..547224e781b1 100644 --- a/packages/SystemUI/res-keyguard/values-ro/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Modelul este necesar după repornirea dispozitivului"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Codul PIN este necesar după repornirea dispozitivului"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Parola este necesară după repornirea dispozitivului"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Modelul este necesar pentru securitate suplimentară"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Codul PIN este necesar pentru securitate suplimentară"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Parola este necesară pentru securitate suplimentară"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispozitiv blocat de administrator"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Dispozitivul a fost blocat manual"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nu este recunoscut"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Prestabilit"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Balon"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogic"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml index 2b8f8d6a93f8..f1945ad3fb03 100644 --- a/packages/SystemUI/res-keyguard/values-ru/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"После перезагрузки устройства необходимо ввести графический ключ"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"После перезагрузки устройства необходимо ввести PIN-код"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"После перезагрузки устройства необходимо ввести пароль"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"В качестве дополнительной меры безопасности введите графический ключ"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"В качестве дополнительной меры безопасности введите PIN-код"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"В качестве дополнительной меры безопасности введите пароль"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"В целях дополнительной безопасности используйте графический ключ"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"В целях дополнительной безопасности используйте PIN-код"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"В целях дополнительной безопасности используйте пароль"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Устройство заблокировано администратором"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Устройство было заблокировано вручную"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Не распознано"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"По умолчанию"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Пузырь"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Стрелки"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Чтобы продолжить, разблокируйте устройство"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml index 4e911defffb6..e5862c358002 100644 --- a/packages/SystemUI/res-keyguard/values-si/strings.xml +++ b/packages/SystemUI/res-keyguard/values-si/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"උපාංගය නැවත ආරම්භ වූ පසු රටාව අවශ්යයි"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"උපාංගය නැවත ආරම්භ වූ පසු PIN අංකය අවශ්යයි"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"උපාංගය නැවත ආරම්භ වූ පසු මුරපදය අවශ්යයි"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"අමතර ආරක්ෂාව සඳහා රටාව අවශ්යයි"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"අමතර ආරක්ෂාව සඳහා PIN අංකය අවශ්යයි"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"අමතර ආරක්ෂාව සඳහා මුරපදය අවශ්යයි"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ඔබගේ පරිපාලක විසින් උපාංගය අගුළු දමා ඇත"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"උපාංගය හස්තීයව අගුලු දමන ලදී"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"හඳුනා නොගන්නා ලදී"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"පෙරනිමි"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"බුබුළ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ප්රතිසමය"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml index f2d68e3763d3..efe4ec864448 100644 --- a/packages/SystemUI/res-keyguard/values-sk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Po reštartovaní zariadenia musíte zadať bezpečnostný vzor"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Po reštartovaní zariadenia musíte zadať kód PIN"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Po reštartovaní zariadenia musíte zadať heslo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Na ďalšie zabezpečenie musíte zadať bezpečnostný vzor"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Na ďalšie zabezpečenie musíte zadať kód PIN"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Na ďalšie zabezpečenie musíte zadať heslo"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Zariadenie zamkol správca"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Zariadenie bolo uzamknuté ručne"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nerozpoznané"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Predvolený"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bublina"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógový"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml index 772308f9f658..52726c225498 100644 --- a/packages/SystemUI/res-keyguard/values-sl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Po vnovičnem zagonu naprave je treba vnesti vzorec"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Po vnovičnem zagonu naprave je treba vnesti kodo PIN"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Po vnovičnem zagonu naprave je treba vnesti geslo"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Zaradi dodatne varnosti morate vnesti vzorec"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Zaradi dodatne varnosti morate vnesti kodo PIN"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Zaradi dodatne varnosti morate vnesti geslo"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Napravo je zaklenil skrbnik"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Naprava je bila ročno zaklenjena"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ni prepoznano"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Privzeto"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Mehurček"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogno"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml index c7584622823c..a0a55944eced 100644 --- a/packages/SystemUI/res-keyguard/values-sq/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Kërkohet motivi pas rinisjes së pajisjes"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Kërkohet kodi PIN pas rinisjes së pajisjes"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Kërkohet fjalëkalimi pas rinisjes së pajisjes"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Kërkohet motivi për më shumë siguri"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Kërkohet kodi PIN për më shumë siguri"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Kërkohet fjalëkalimi për më shumë siguri"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Pajisja është e kyçur nga administratori"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Pajisja është kyçur manualisht"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nuk njihet"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"E parazgjedhur"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Flluskë"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analoge"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml index e6fe8531ff4c..e634fdcb586e 100644 --- a/packages/SystemUI/res-keyguard/values-sr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Треба да унесете шаблон када се уређај поново покрене"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Треба да унесете PIN када се уређај поново покрене"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Треба да унесете лозинку када се уређај поново покрене"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Треба да унесете шаблон ради додатне безбедности"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Треба да унесете PIN ради додатне безбедности"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Треба да унесете лозинку ради додатне безбедности"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Администратор је закључао уређај"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Уређај је ручно закључан"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Није препознат"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Подразумевани"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Мехурићи"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Аналогни"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml index fa241d96cfae..fc9beb1286a6 100644 --- a/packages/SystemUI/res-keyguard/values-sv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Du måste rita mönster när du har startat om enheten"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Du måste ange pinkod när du har startat om enheten"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Du måste ange lösenord när du har startat om enheten"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Du måste rita mönster för ytterligare säkerhet"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Du måste ange pinkod för ytterligare säkerhet"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Du måste ange lösenord för ytterligare säkerhet"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administratören har låst enheten"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Enheten har låsts manuellt"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Identifierades inte"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Standard"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubbla"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml index 791bceb071e9..bcab24b013bb 100644 --- a/packages/SystemUI/res-keyguard/values-sw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Unafaa kuchora mchoro baada ya kuwasha kifaa upya"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Unafaa kuweka PIN baada ya kuwasha kifaa upya"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Unafaa kuweka nenosiri baada ya kuwasha kifaa upya"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Mchoro unahitajika ili kuongeza usalama"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN inahitajika ili kuongeza usalama"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Nenosiri linahitajika ili kuongeza usalama."</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Msimamizi amefunga kifaa"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Umefunga kifaa mwenyewe"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Haitambuliwi"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Chaguomsingi"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Kiputo"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogi"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml index 271657d9f0a1..88d5760e7f6c 100644 --- a/packages/SystemUI/res-keyguard/values-ta/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"சாதனத்தை மீண்டும் தொடங்கியதும், பேட்டர்னை வரைய வேண்டும்"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"சாதனத்தை மீண்டும் தொடங்கியதும், பின்னை உள்ளிட வேண்டும்"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"சாதனத்தை மீண்டும் தொடங்கியதும், கடவுச்சொல்லை உள்ளிட வேண்டும்"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"கூடுதல் பாதுகாப்பிற்கு, பேட்டர்னை வரைய வேண்டும்"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"கூடுதல் பாதுகாப்பிற்கு, பின்னை உள்ளிட வேண்டும்"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"கூடுதல் பாதுகாப்பிற்கு, கடவுச்சொல்லை உள்ளிட வேண்டும்"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"நிர்வாகி சாதனத்தைப் பூட்டியுள்ளார்"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"பயனர் சாதனத்தைப் பூட்டியுள்ளார்"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"அடையாளங்காணபடவில்லை"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"இயல்பு"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"பபிள்"</string> <string name="clock_title_analog" msgid="8409262532900918273">"அனலாக்"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index f62e667ee26d..3a0111a193bd 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"పరికరాన్ని పునఃప్రారంభించిన తర్వాత నమూనాను గీయాలి"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"డివైజ్ను పునఃప్రారంభించిన తర్వాత పిన్ నమోదు చేయాలి"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"పరికరాన్ని పునఃప్రారంభించిన తర్వాత పాస్వర్డ్ను నమోదు చేయాలి"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"అదనపు సెక్యూరిటీ కోసం ఆకృతి అవసరం"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"అదనపు సెక్యూరిటీ కోసం పిన్ ఎంటర్ చేయాలి"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"అదనపు సెక్యూరిటీ కోసం పాస్వర్డ్ను ఎంటర్ చేయాలి"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"పరికరం నిర్వాహకుల ద్వారా లాక్ చేయబడింది"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"పరికరం మాన్యువల్గా లాక్ చేయబడింది"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"గుర్తించలేదు"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ఆటోమేటిక్"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"బబుల్"</string> <string name="clock_title_analog" msgid="8409262532900918273">"ఎనలాగ్"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml index 62a83bcf9d7a..14a65a074f87 100644 --- a/packages/SystemUI/res-keyguard/values-th/strings.xml +++ b/packages/SystemUI/res-keyguard/values-th/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ต้องวาดรูปแบบหลังจากอุปกรณ์รีสตาร์ท"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"ต้องระบุ PIN หลังจากอุปกรณ์รีสตาร์ท"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"ต้องป้อนรหัสผ่านหลังจากอุปกรณ์รีสตาร์ท"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ต้องวาดรูปแบบเพื่อความปลอดภัยเพิ่มเติม"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ต้องระบุ PIN เพื่อความปลอดภัยเพิ่มเติม"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ต้องป้อนรหัสผ่านเพื่อความปลอดภัยเพิ่มเติม"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"ใช้รูปแบบแทนเพื่อเพิ่มความปลอดภัย"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"ใช้ PIN แทนเพื่อเพิ่มความปลอดภัย"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"ใช้รหัสผ่านแทนเพื่อเพิ่มความปลอดภัย"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ผู้ดูแลระบบล็อกอุปกรณ์"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"มีการล็อกอุปกรณ์ด้วยตัวเอง"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"ไม่รู้จัก"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"ค่าเริ่มต้น"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"บับเบิล"</string> <string name="clock_title_analog" msgid="8409262532900918273">"แอนะล็อก"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"ปลดล็อกอุปกรณ์ของคุณเพื่อดำเนินการต่อ"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml index 524ea4782506..7936058581ae 100644 --- a/packages/SystemUI/res-keyguard/values-tl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Kailangan ng pattern pagkatapos mag-restart ng device"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Kailangan ng PIN pagkatapos mag-restart ng device"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Kailangan ng password pagkatapos mag-restart ng device"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Kinakailangan ang pattern para sa karagdagang seguridad"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Kinakailangan ang PIN para sa karagdagang seguridad"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Kinakailangan ang password para sa karagdagang seguridad"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Para sa karagdagang seguridad, gumamit na lang ng pattern"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Para sa karagdagang seguridad, gumamit na lang ng PIN"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Para sa karagdagang seguridad, gumamit na lang ng password"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Na-lock ng admin ang device"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Manual na na-lock ang device"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Hindi nakilala"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Default"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bubble"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"I-unlock ang iyong device para magpatuloy"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml index 54aaae38b18c..e5207623adc2 100644 --- a/packages/SystemUI/res-keyguard/values-tr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Cihaz yeniden başladıktan sonra desen gerekir"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Cihaz yeniden başladıktan sonra PIN gerekir"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Cihaz yeniden başladıktan sonra şifre gerekir"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Ek güvenlik için desen gerekir"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Ek güvenlik için PIN gerekir"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Ek güvenlik için şifre gerekir"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Cihaz, yönetici tarafından kilitlendi"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Cihazın manuel olarak kilitlendi"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tanınmadı"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Varsayılan"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Baloncuk"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml index 6144c1c4e0d5..613181d6c96f 100644 --- a/packages/SystemUI/res-keyguard/values-uk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Після перезавантаження пристрою потрібно ввести ключ"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Після перезавантаження пристрою потрібно ввести PIN-код"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Після перезавантаження пристрою потрібно ввести пароль"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Для додаткового захисту потрібно ввести ключ"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Для додаткового захисту потрібно ввести PIN-код"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Для додаткового захисту потрібно ввести пароль"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Адміністратор заблокував пристрій"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Пристрій заблоковано вручну"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Не розпізнано"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"За умовчанням"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Бульбашковий"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Аналоговий"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml index 4e778413775e..a122f8537611 100644 --- a/packages/SystemUI/res-keyguard/values-ur/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"آلہ دوبارہ چالو ہونے کے بعد پیٹرن درکار ہوتا ہے"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"آلہ دوبارہ چالو ہونے کے بعد PIN درکار ہوتا ہے"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"آلہ دوبارہ چالو ہونے کے بعد پاس ورڈ درکار ہوتا ہے"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"اضافی سیکیورٹی کیلئے پیٹرن درکار ہے"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"اضافی سیکیورٹی کیلئے PIN درکار ہے"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"اضافی سیکیورٹی کیلئے پاس ورڈ درکار ہے"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"آلہ منتظم کی جانب سے مقفل ہے"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"آلہ کو دستی طور پر مقفل کیا گیا تھا"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"تسلیم شدہ نہیں ہے"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"ڈیفالٹ"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"بلبلہ"</string> <string name="clock_title_analog" msgid="8409262532900918273">"اینالاگ"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml index afaf7464d091..2cc9724dc53b 100644 --- a/packages/SystemUI/res-keyguard/values-uz/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml @@ -78,9 +78,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Qurilma qayta ishga tushganidan keyin grafik kalitni kiritish zarur"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Qurilma qayta ishga tushganidan keyin PIN kodni kiritish zarur"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Qurilma qayta ishga tushganidan keyin parolni kiritish zarur"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Qo‘shimcha xavfsizlik chorasi sifatida grafik kalit talab qilinadi"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Qo‘shimcha xavfsizlik chorasi sifatida PIN kod talab qilinadi"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Qo‘shimcha xavfsizlik chorasi sifatida parol talab qilinadi"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="5514969660010197363">"Qoʻshimcha xavfsizlik maqsadida oʻrniga grafik kalitdan foydalaning"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="4227962059353859376">"Qoʻshimcha xavfsizlik maqsadida oʻrniga PIN koddan foydalaning"</string> + <string name="kg_prompt_reason_timeout_password" msgid="8810879144143933690">"Qoʻshimcha xavfsizlik maqsadida oʻrniga paroldan foydalaning"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Qurilma administrator tomonidan bloklangan"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Qurilma qo‘lda qulflangan"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Aniqlanmadi"</string> @@ -90,4 +90,5 @@ <string name="clock_title_default" msgid="6342735240617459864">"Odatiy"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Pufaklar"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analog"</string> + <string name="keyguard_unlock_to_continue" msgid="7509503484250597743">"Davom etish uchun qurilmangizni qulfdan chiqaring"</string> </resources> diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml index 1d6cfa85e4ed..e7c9295815ad 100644 --- a/packages/SystemUI/res-keyguard/values-vi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Yêu cầu hình mở khóa sau khi thiết bị khởi động lại"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Yêu cầu mã PIN sau khi thiết bị khởi động lại"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Yêu cầu mật khẩu sau khi thiết bị khởi động lại"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Yêu cầu hình mở khóa để bảo mật thêm"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Yêu cầu mã PIN để bảo mật thêm"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Yêu cầu mật khẩu để bảo mật thêm"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Thiết bị đã bị quản trị viên khóa"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Thiết bị đã bị khóa theo cách thủ công"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Không nhận dạng được"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Mặc định"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bong bóng"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Đồng hồ kim"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml index 8c8507ed06fa..d37d645b15ee 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"重启设备后需要绘制解锁图案"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"重启设备后需要输入 PIN 码"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"重启设备后需要输入密码"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"需要绘制解锁图案以进一步确保安全"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"需要输入 PIN 码以进一步确保安全"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"需要输入密码以进一步确保安全"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"管理员已锁定设备"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"此设备已手动锁定"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"无法识别"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"默认"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"泡泡"</string> <string name="clock_title_analog" msgid="8409262532900918273">"指针"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml index c331a925be39..9dbb8f2dac73 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"裝置重新啟動後,必須畫出上鎖圖案才能使用"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"裝置重新啟動後,必須輸入 PIN 碼才能使用"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"裝置重新啟動後,必須輸入密碼才能使用"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"請務必畫出上鎖圖案,以進一步確保安全"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"請務必輸入 PIN 碼,以進一步確保安全"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"請務必輸入密碼,以進一步確保安全"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"裝置已由管理員鎖定"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"使用者已手動將裝置上鎖"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"未能識別"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"預設"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"泡泡"</string> <string name="clock_title_analog" msgid="8409262532900918273">"指針"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml index 1e1bec3ef76a..ebb88e13194b 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"裝置重新啟動後需要畫出解鎖圖案"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"裝置重新啟動後需要輸入 PIN 碼"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"裝置重新啟動後需要輸入密碼"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"請畫出解鎖圖案,以進一步確保資訊安全"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"請輸入 PIN 碼,以進一步確保資訊安全"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"請輸入密碼,以進一步確保資訊安全"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"管理員已鎖定裝置"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"裝置已手動鎖定"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"無法識別"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"預設"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"泡泡"</string> <string name="clock_title_analog" msgid="8409262532900918273">"類比"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml index c8f78ea441f5..57e56f713536 100644 --- a/packages/SystemUI/res-keyguard/values-zu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml @@ -78,9 +78,12 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Iphethini iyadingeka ngemuva kokuqala kabusha kwedivayisi"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"Iphinikhodi iyadingeka ngemuva kokuqala kabusha kwedivayisi"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"Iphasiwedi iyadingeka ngemuva kokuqala kabusha kwedivayisi"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Kudingeka iphethini ngokuvikeleka okungeziwe"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Kudingeka iphinikhodi ngokuvikeleka okungeziwe"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Iphasiwedi idingelwa ukuvikela okungeziwe"</string> + <!-- no translation found for kg_prompt_reason_timeout_pattern (5514969660010197363) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_pin (4227962059353859376) --> + <skip /> + <!-- no translation found for kg_prompt_reason_timeout_password (8810879144143933690) --> + <skip /> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Idivayisi ikhiywe ngumlawuli"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Idivayisi ikhiywe ngokwenza"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Akwaziwa"</string> @@ -90,4 +93,6 @@ <string name="clock_title_default" msgid="6342735240617459864">"Okuzenzekelayo"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Ibhamuza"</string> <string name="clock_title_analog" msgid="8409262532900918273">"I-Analog"</string> + <!-- no translation found for keyguard_unlock_to_continue (7509503484250597743) --> + <skip /> </resources> diff --git a/packages/SystemUI/res/drawable-hdpi/textfield_default_filled.9.png b/packages/SystemUI/res/drawable-hdpi/textfield_default_filled.9.png Binary files differnew file mode 100644 index 000000000000..3dd997fade6c --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/textfield_default_filled.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/textfield_default_filled.9.png b/packages/SystemUI/res/drawable-mdpi/textfield_default_filled.9.png Binary files differnew file mode 100644 index 000000000000..80aba01091fe --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/textfield_default_filled.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/textfield_default_filled.9.png b/packages/SystemUI/res/drawable-xhdpi/textfield_default_filled.9.png Binary files differnew file mode 100644 index 000000000000..b3f89ed7ea7a --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/textfield_default_filled.9.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/textfield_default_filled.9.png b/packages/SystemUI/res/drawable-xxhdpi/textfield_default_filled.9.png Binary files differnew file mode 100644 index 000000000000..efa2cb988ac1 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/textfield_default_filled.9.png diff --git a/packages/SystemUI/res/drawable/edit_text_filled.xml b/packages/SystemUI/res/drawable/edit_text_filled.xml new file mode 100644 index 000000000000..cca34d456078 --- /dev/null +++ b/packages/SystemUI/res/drawable/edit_text_filled.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:insetLeft="4dp" + android:insetRight="4dp" + android:insetTop="10dp" + android:insetBottom="10dp"> + <selector> + <item android:state_enabled="false"> + <nine-patch android:src="@drawable/textfield_default_filled" + android:tint="?android:attr/colorControlNormal" /> + </item> + <item android:state_pressed="false" android:state_focused="false"> + <nine-patch android:src="@drawable/textfield_default_filled" + android:tint="?android:attr/colorControlNormal" /> + </item> + <item> + <nine-patch android:src="@drawable/textfield_default_filled" + android:tint="?android:attr/colorControlActivated" /> + </item> + </selector> +</inset> diff --git a/packages/SystemUI/res/layout-land/auth_credential_password_view.xml b/packages/SystemUI/res/layout-land/auth_credential_password_view.xml index da76c8d0b11a..3bcc37a478c9 100644 --- a/packages/SystemUI/res/layout-land/auth_credential_password_view.xml +++ b/packages/SystemUI/res/layout-land/auth_credential_password_view.xml @@ -16,46 +16,74 @@ <com.android.systemui.biometrics.AuthCredentialPasswordView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" - android:gravity="center_horizontal" - android:elevation="@dimen/biometric_dialog_elevation"> + android:orientation="horizontal" + android:elevation="@dimen/biometric_dialog_elevation" + android:theme="?app:attr/lockPinPasswordStyle"> - <TextView - android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="@style/TextAppearance.AuthCredential.Title"/> + <RelativeLayout + android:id="@+id/auth_credential_header" + style="?headerStyle" + android:layout_width="wrap_content" + android:layout_height="match_parent"> - <TextView - android:id="@+id/subtitle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="@style/TextAppearance.AuthCredential.Subtitle"/> + <ImageView + android:id="@+id/icon" + style="?headerIconStyle" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:contentDescription="@null"/> - <TextView - android:id="@+id/description" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="@style/TextAppearance.AuthCredential.Description"/> + <TextView + android:id="@+id/title" + style="?titleTextAppearance" + android:layout_below="@id/icon" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> - <ImeAwareEditText - android:id="@+id/lockPassword" - android:layout_width="208dp" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:minHeight="48dp" - android:gravity="center" - android:inputType="textPassword" - android:maxLength="500" - android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii" - style="@style/TextAppearance.AuthCredential.PasswordEntry"/> - - <TextView - android:id="@+id/error" - android:layout_width="match_parent" + <TextView + android:id="@+id/subtitle" + style="?subTitleTextAppearance" + android:layout_below="@id/title" + android:layout_alignParentLeft="true" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/description" + style="?descriptionTextAppearance" + android:layout_below="@id/subtitle" + android:layout_alignParentLeft="true" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + </RelativeLayout> + + <LinearLayout + android:id="@+id/auth_credential_input" + android:layout_width="wrap_content" android:layout_height="wrap_content" - style="@style/TextAppearance.AuthCredential.Error"/> + android:orientation="vertical"> + + <ImeAwareEditText + android:id="@+id/lockPassword" + style="?passwordTextAppearance" + android:layout_width="208dp" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii" + android:inputType="textPassword" + android:minHeight="48dp" /> + + <TextView + android:id="@+id/error" + style="?errorTextAppearance" + android:layout_gravity="center" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + </LinearLayout> </com.android.systemui.biometrics.AuthCredentialPasswordView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml index 19a85fec1397..a3dd334bd667 100644 --- a/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml +++ b/packages/SystemUI/res/layout-land/auth_credential_pattern_view.xml @@ -16,91 +16,71 @@ <com.android.systemui.biometrics.AuthCredentialPatternView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" - android:elevation="@dimen/biometric_dialog_elevation"> + android:elevation="@dimen/biometric_dialog_elevation" + android:theme="?app:attr/lockPatternStyle"> - <LinearLayout + <RelativeLayout + android:id="@+id/auth_credential_header" + style="?headerStyle" android:layout_width="0dp" android:layout_height="match_parent" - android:layout_weight="1" - android:gravity="center" - android:orientation="vertical"> - - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1"/> + android:layout_weight="1"> <ImageView android:id="@+id/icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content"/> + style="?headerIconStyle" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:contentDescription="@null"/> <TextView android:id="@+id/title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="@style/TextAppearance.AuthCredential.Title"/> + style="?titleTextAppearance" + android:layout_below="@id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> <TextView android:id="@+id/subtitle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="@style/TextAppearance.AuthCredential.Subtitle"/> + style="?subTitleTextAppearance" + android:layout_below="@id/title" + android:layout_alignParentLeft="true" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> <TextView android:id="@+id/description" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="@style/TextAppearance.AuthCredential.Description"/> + style="?descriptionTextAppearance" + android:layout_below="@id/subtitle" + android:layout_alignParentLeft="true" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1"/> + </RelativeLayout> + + <FrameLayout + android:layout_weight="1" + style="?containerStyle" + android:layout_width="0dp" + android:layout_height="match_parent"> + + <com.android.internal.widget.LockPatternView + android:id="@+id/lockPattern" + android:layout_gravity="center" + android:layout_width="match_parent" + android:layout_height="match_parent"/> <TextView android:id="@+id/error" + style="?errorTextAppearance" android:layout_width="match_parent" android:layout_height="wrap_content" - style="@style/TextAppearance.AuthCredential.Error"/> - - <Space - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_weight="1"/> - - </LinearLayout> - - <LinearLayout - android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_weight="1" - android:orientation="vertical" - android:gravity="center" - android:paddingLeft="0dp" - android:paddingRight="0dp" - android:paddingTop="0dp" - android:paddingBottom="16dp" - android:clipToPadding="false"> - - <FrameLayout - android:layout_width="wrap_content" - android:layout_height="0dp" - android:layout_weight="1" - style="@style/LockPatternContainerStyle"> - - <com.android.internal.widget.LockPatternView - android:id="@+id/lockPattern" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center" - style="@style/LockPatternStyleBiometricPrompt"/> - - </FrameLayout> + android:layout_gravity="center_horizontal|bottom"/> - </LinearLayout> + </FrameLayout> </com.android.systemui.biometrics.AuthCredentialPatternView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/auth_credential_password_view.xml b/packages/SystemUI/res/layout/auth_credential_password_view.xml index 0ff1db2ef694..774b335f913e 100644 --- a/packages/SystemUI/res/layout/auth_credential_password_view.xml +++ b/packages/SystemUI/res/layout/auth_credential_password_view.xml @@ -16,74 +16,71 @@ <com.android.systemui.biometrics.AuthCredentialPasswordView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:elevation="@dimen/biometric_dialog_elevation" - android:orientation="vertical"> + android:orientation="vertical" + android:theme="?app:attr/lockPinPasswordStyle"> <RelativeLayout + android:id="@+id/auth_credential_header" + style="?headerStyle" android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - - <LinearLayout - android:id="@+id/auth_credential_header" - style="@style/AuthCredentialHeaderStyle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentTop="true"> + android:layout_height="match_parent"> - <ImageView - android:id="@+id/icon" - android:layout_width="48dp" - android:layout_height="48dp" - android:contentDescription="@null" /> + <ImageView + android:id="@+id/icon" + style="?headerIconStyle" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:contentDescription="@null"/> - <TextView - android:id="@+id/title" - style="@style/TextAppearance.AuthNonBioCredential.Title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - - <TextView - android:id="@+id/subtitle" - style="@style/TextAppearance.AuthNonBioCredential.Subtitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - - <TextView - android:id="@+id/description" - style="@style/TextAppearance.AuthNonBioCredential.Description" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> + <TextView + android:id="@+id/title" + style="?titleTextAppearance" + android:layout_below="@id/icon" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> - </LinearLayout> + <TextView + android:id="@+id/subtitle" + style="?subTitleTextAppearance" + android:layout_below="@id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> - <LinearLayout + <TextView + android:id="@+id/description" + style="?descriptionTextAppearance" + android:layout_below="@id/subtitle" android:layout_width="match_parent" - android:layout_height="match_parent" - android:gravity="center" - android:orientation="vertical" - android:layout_alignParentBottom="true"> + android:layout_height="wrap_content"/> + </RelativeLayout> - <ImeAwareEditText - android:id="@+id/lockPassword" - style="@style/TextAppearance.AuthCredential.PasswordEntry" - android:layout_width="208dp" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii" - android:inputType="textPassword" - android:minHeight="48dp" /> + <LinearLayout + android:id="@+id/auth_credential_input" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> - <TextView - android:id="@+id/error" - style="@style/TextAppearance.AuthNonBioCredential.Error" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> + <ImeAwareEditText + android:id="@+id/lockPassword" + style="?passwordTextAppearance" + android:layout_width="208dp" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii" + android:inputType="textPassword" + android:minHeight="48dp" /> - </LinearLayout> + <TextView + android:id="@+id/error" + style="?errorTextAppearance" + android:layout_gravity="center_horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> - </RelativeLayout> + </LinearLayout> </com.android.systemui.biometrics.AuthCredentialPasswordView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml index dada9813c320..4af997017bba 100644 --- a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml +++ b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml @@ -16,87 +16,66 @@ <com.android.systemui.biometrics.AuthCredentialPatternView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:gravity="center_horizontal" - android:elevation="@dimen/biometric_dialog_elevation"> + android:elevation="@dimen/biometric_dialog_elevation" + android:theme="?app:attr/lockPatternStyle"> <RelativeLayout + android:id="@+id/auth_credential_header" + style="?headerStyle" android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical"> - - <LinearLayout - android:id="@+id/auth_credential_header" - style="@style/AuthCredentialHeaderStyle" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <ImageView - android:id="@+id/icon" - android:layout_width="48dp" - android:layout_height="48dp" - android:contentDescription="@null" /> - - <TextView - android:id="@+id/title" - style="@style/TextAppearance.AuthNonBioCredential.Title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - - <TextView - android:id="@+id/subtitle" - style="@style/TextAppearance.AuthNonBioCredential.Subtitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content"> + + <ImageView + android:id="@+id/icon" + style="?headerIconStyle" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:contentDescription="@null"/> + + <TextView + android:id="@+id/title" + style="?titleTextAppearance" + android:layout_below="@id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + + <TextView + android:id="@+id/subtitle" + style="?subTitleTextAppearance" + android:layout_below="@id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + + <TextView + android:id="@+id/description" + style="?descriptionTextAppearance" + android:layout_below="@id/subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + </RelativeLayout> - <TextView - android:id="@+id/description" - style="@style/TextAppearance.AuthNonBioCredential.Description" - android:layout_width="wrap_content" - android:layout_height="wrap_content" /> - </LinearLayout> + <FrameLayout + android:id="@+id/auth_credential_container" + style="?containerStyle" + android:layout_width="match_parent" + android:layout_height="match_parent"> - <LinearLayout + <com.android.internal.widget.LockPatternView + android:id="@+id/lockPattern" + android:layout_gravity="center" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_below="@id/auth_credential_header" - android:gravity="center" - android:orientation="vertical" - android:paddingBottom="16dp" - android:paddingTop="60dp"> + android:layout_height="match_parent"/> - <FrameLayout - style="@style/LockPatternContainerStyle" - android:layout_width="wrap_content" - android:layout_height="0dp" - android:layout_weight="1"> - - <com.android.internal.widget.LockPatternView - android:id="@+id/lockPattern" - style="@style/LockPatternStyle" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center" /> - - </FrameLayout> - - </LinearLayout> - - <LinearLayout + <TextView + android:id="@+id/error" + style="?errorTextAppearance" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_alignParentBottom="true"> - - <TextView - android:id="@+id/error" - style="@style/TextAppearance.AuthNonBioCredential.Error" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> - - </LinearLayout> - - </RelativeLayout> + android:layout_gravity="center_horizontal|bottom"/> + </FrameLayout> </com.android.systemui.biometrics.AuthCredentialPatternView>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml index 89191984b9e8..aefd9981d02e 100644 --- a/packages/SystemUI/res/values-land/styles.xml +++ b/packages/SystemUI/res/values-land/styles.xml @@ -18,4 +18,42 @@ <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer"> <item name="android:layout_width">360dp</item> </style> + + <style name="AuthCredentialHeaderStyle"> + <item name="android:paddingStart">48dp</item> + <item name="android:paddingEnd">24dp</item> + <item name="android:paddingTop">48dp</item> + <item name="android:paddingBottom">10dp</item> + <item name="android:gravity">top|left</item> + </style> + + <style name="AuthCredentialPatternContainerStyle"> + <item name="android:gravity">center</item> + <item name="android:maxHeight">320dp</item> + <item name="android:maxWidth">320dp</item> + <item name="android:minHeight">200dp</item> + <item name="android:minWidth">200dp</item> + <item name="android:paddingHorizontal">60dp</item> + <item name="android:paddingVertical">20dp</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Title"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">6dp</item> + <item name="android:textSize">36dp</item> + <item name="android:focusable">true</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Subtitle"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">6dp</item> + <item name="android:textSize">18sp</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Description"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">6dp</item> + <item name="android:textSize">18sp</item> + </style> + </resources> diff --git a/packages/SystemUI/res/values-sw600dp-land/styles.xml b/packages/SystemUI/res/values-sw600dp-land/styles.xml new file mode 100644 index 000000000000..8148d3dfaf7d --- /dev/null +++ b/packages/SystemUI/res/values-sw600dp-land/styles.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + + <style name="AuthCredentialPatternContainerStyle"> + <item name="android:gravity">center</item> + <item name="android:maxHeight">420dp</item> + <item name="android:maxWidth">420dp</item> + <item name="android:minHeight">200dp</item> + <item name="android:minWidth">200dp</item> + <item name="android:paddingHorizontal">120dp</item> + <item name="android:paddingVertical">40dp</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Title"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">16dp</item> + <item name="android:textSize">36sp</item> + <item name="android:focusable">true</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Subtitle"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">16dp</item> + <item name="android:textSize">18sp</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Description"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">16dp</item> + <item name="android:textSize">18sp</item> + </style> +</resources> diff --git a/packages/SystemUI/res/values-sw600dp-port/styles.xml b/packages/SystemUI/res/values-sw600dp-port/styles.xml new file mode 100644 index 000000000000..771de08cb360 --- /dev/null +++ b/packages/SystemUI/res/values-sw600dp-port/styles.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + + <style name="AuthCredentialHeaderStyle"> + <item name="android:paddingStart">120dp</item> + <item name="android:paddingEnd">120dp</item> + <item name="android:paddingTop">80dp</item> + <item name="android:paddingBottom">10dp</item> + <item name="android:layout_gravity">top</item> + </style> + + <style name="AuthCredentialPatternContainerStyle"> + <item name="android:gravity">center</item> + <item name="android:maxHeight">420dp</item> + <item name="android:maxWidth">420dp</item> + <item name="android:minHeight">200dp</item> + <item name="android:minWidth">200dp</item> + <item name="android:paddingHorizontal">180dp</item> + <item name="android:paddingVertical">80dp</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Title"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">24dp</item> + <item name="android:textSize">36sp</item> + <item name="android:focusable">true</item> + </style> + +</resources> diff --git a/packages/SystemUI/res/values-sw720dp-land/styles.xml b/packages/SystemUI/res/values-sw720dp-land/styles.xml new file mode 100644 index 000000000000..f9ed67d89de7 --- /dev/null +++ b/packages/SystemUI/res/values-sw720dp-land/styles.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + + <style name="AuthCredentialPatternContainerStyle"> + <item name="android:gravity">center</item> + <item name="android:maxHeight">420dp</item> + <item name="android:maxWidth">420dp</item> + <item name="android:minHeight">200dp</item> + <item name="android:minWidth">200dp</item> + <item name="android:paddingHorizontal">120dp</item> + <item name="android:paddingVertical">40dp</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Title"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">16dp</item> + <item name="android:textSize">36sp</item> + <item name="android:focusable">true</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Subtitle"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">16dp</item> + <item name="android:textSize">18sp</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Description"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">16dp</item> + <item name="android:textSize">18sp</item> + </style> + +</resources> diff --git a/packages/SystemUI/res/values-sw720dp-port/styles.xml b/packages/SystemUI/res/values-sw720dp-port/styles.xml new file mode 100644 index 000000000000..78d299c483e6 --- /dev/null +++ b/packages/SystemUI/res/values-sw720dp-port/styles.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + + <style name="AuthCredentialHeaderStyle"> + <item name="android:paddingStart">120dp</item> + <item name="android:paddingEnd">120dp</item> + <item name="android:paddingTop">80dp</item> + <item name="android:paddingBottom">10dp</item> + <item name="android:layout_gravity">top</item> + </style> + + <style name="AuthCredentialPatternContainerStyle"> + <item name="android:gravity">center</item> + <item name="android:maxHeight">420dp</item> + <item name="android:maxWidth">420dp</item> + <item name="android:minHeight">200dp</item> + <item name="android:minWidth">200dp</item> + <item name="android:paddingHorizontal">240dp</item> + <item name="android:paddingVertical">120dp</item> + </style> + + <style name="TextAppearance.AuthNonBioCredential.Title"> + <item name="android:fontFamily">google-sans</item> + <item name="android:layout_marginTop">24dp</item> + <item name="android:textSize">36sp</item> + <item name="android:focusable">true</item> + </style> + +</resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index bbe4b6c70c1c..f5fc7ee53f2e 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -672,7 +672,7 @@ <string name="data_connection_no_internet" msgid="691058178914184544">"沒有網際網路連線"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"開啟「<xliff:g id="ID_1">%s</xliff:g>」設定。"</string> <string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"編輯設定順序。"</string> - <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源按鈕選單"</string> + <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源鍵選單"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"鎖定畫面"</string> <string name="thermal_shutdown_title" msgid="2702966892682930264">"手機先前過熱,因此關閉電源"</string> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 9a71995383ac..df0659d67afe 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -191,5 +191,18 @@ <declare-styleable name="DelayableMarqueeTextView"> <attr name="marqueeDelay" format="integer" /> </declare-styleable> + + <declare-styleable name="AuthCredentialView"> + <attr name="lockPatternStyle" format="reference" /> + <attr name="lockPinPasswordStyle" format="reference" /> + <attr name="containerStyle" format="reference" /> + <attr name="headerStyle" format="reference" /> + <attr name="headerIconStyle" format="reference" /> + <attr name="titleTextAppearance" format="reference" /> + <attr name="subTitleTextAppearance" format="reference" /> + <attr name="descriptionTextAppearance" format="reference" /> + <attr name="passwordTextAppearance" format="reference" /> + <attr name="errorTextAppearance" format="reference"/> + </declare-styleable> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index cf100cb04a7b..93926ef9e780 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -950,6 +950,9 @@ <dimen name="biometric_dialog_width">240dp</dimen> <dimen name="biometric_dialog_height">240dp</dimen> + <!-- Biometric Auth Credential values --> + <dimen name="biometric_auth_icon_size">48dp</dimen> + <!-- Starting text size in sp of batteryLevel for wireless charging animation --> <item name="wireless_charging_anim_battery_level_text_size_start" format="float" type="dimen"> 0 diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index b5011dfaf6eb..e76887babc50 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -197,8 +197,9 @@ <style name="TextAppearance.AuthNonBioCredential.Title"> <item name="android:fontFamily">google-sans</item> - <item name="android:layout_marginTop">20dp</item> - <item name="android:textSize">36sp</item> + <item name="android:layout_marginTop">24dp</item> + <item name="android:textSize">36dp</item> + <item name="android:focusable">true</item> </style> <style name="TextAppearance.AuthNonBioCredential.Subtitle"> @@ -210,12 +211,10 @@ <style name="TextAppearance.AuthNonBioCredential.Description"> <item name="android:fontFamily">google-sans</item> <item name="android:layout_marginTop">20dp</item> - <item name="android:textSize">16sp</item> + <item name="android:textSize">18sp</item> </style> <style name="TextAppearance.AuthNonBioCredential.Error"> - <item name="android:paddingTop">6dp</item> - <item name="android:paddingBottom">18dp</item> <item name="android:paddingHorizontal">24dp</item> <item name="android:textSize">14sp</item> <item name="android:textColor">?android:attr/colorError</item> @@ -224,20 +223,43 @@ <style name="TextAppearance.AuthCredential.PasswordEntry" parent="@android:style/TextAppearance.DeviceDefault"> <item name="android:gravity">center</item> + <item name="android:paddingTop">28dp</item> <item name="android:singleLine">true</item> <item name="android:textColor">?android:attr/colorForeground</item> <item name="android:textSize">24sp</item> + <item name="android:background">@drawable/edit_text_filled</item> </style> <style name="AuthCredentialHeaderStyle"> <item name="android:paddingStart">48dp</item> - <item name="android:paddingEnd">24dp</item> - <item name="android:paddingTop">28dp</item> - <item name="android:paddingBottom">20dp</item> - <item name="android:orientation">vertical</item> + <item name="android:paddingEnd">48dp</item> + <item name="android:paddingTop">48dp</item> + <item name="android:paddingBottom">10dp</item> <item name="android:layout_gravity">top</item> </style> + <style name="AuthCredentialIconStyle"> + <item name="android:layout_width">@dimen/biometric_auth_icon_size</item> + <item name="android:layout_height">@dimen/biometric_auth_icon_size</item> + </style> + + <style name="AuthCredentialPatternContainerStyle"> + <item name="android:gravity">center</item> + <item name="android:maxHeight">420dp</item> + <item name="android:maxWidth">420dp</item> + <item name="android:minHeight">200dp</item> + <item name="android:minWidth">200dp</item> + <item name="android:padding">20dp</item> + </style> + + <style name="AuthCredentialPinPasswordContainerStyle"> + <item name="android:gravity">center</item> + <item name="android:maxHeight">48dp</item> + <item name="android:maxWidth">600dp</item> + <item name="android:minHeight">48dp</item> + <item name="android:minWidth">200dp</item> + </style> + <style name="DeviceManagementDialogTitle"> <item name="android:gravity">center</item> <item name="android:textAppearance">@style/TextAppearance.DeviceManagementDialog.Title</item> @@ -275,7 +297,9 @@ <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_dark</item> <item name="wallpaperTextColorAccent">@color/material_dynamic_primary90</item> <item name="android:colorError">@*android:color/error_color_material_dark</item> - <item name="*android:lockPatternStyle">@style/LockPatternStyle</item> + <item name="*android:lockPatternStyle">@style/LockPatternViewStyle</item> + <item name="lockPatternStyle">@style/LockPatternContainerStyle</item> + <item name="lockPinPasswordStyle">@style/LockPinPasswordContainerStyle</item> <item name="passwordStyle">@style/PasswordTheme</item> <item name="numPadKeyStyle">@style/NumPadKey</item> <item name="backgroundProtectedStyle">@style/BackgroundProtectedStyle</item> @@ -301,27 +325,33 @@ <item name="android:textColor">?attr/wallpaperTextColor</item> </style> - <style name="LockPatternContainerStyle"> - <item name="android:maxHeight">400dp</item> - <item name="android:maxWidth">420dp</item> - <item name="android:minHeight">0dp</item> - <item name="android:minWidth">0dp</item> - <item name="android:paddingHorizontal">60dp</item> - <item name="android:paddingBottom">40dp</item> + <style name="AuthCredentialStyle"> + <item name="*android:regularColor">?android:attr/colorForeground</item> + <item name="*android:successColor">?android:attr/colorForeground</item> + <item name="*android:errorColor">?android:attr/colorError</item> + <item name="*android:dotColor">?android:attr/textColorSecondary</item> + <item name="headerStyle">@style/AuthCredentialHeaderStyle</item> + <item name="headerIconStyle">@style/AuthCredentialIconStyle</item> + <item name="titleTextAppearance">@style/TextAppearance.AuthNonBioCredential.Title</item> + <item name="subTitleTextAppearance">@style/TextAppearance.AuthNonBioCredential.Subtitle</item> + <item name="descriptionTextAppearance">@style/TextAppearance.AuthNonBioCredential.Description</item> + <item name="passwordTextAppearance">@style/TextAppearance.AuthCredential.PasswordEntry</item> + <item name="errorTextAppearance">@style/TextAppearance.AuthNonBioCredential.Error</item> </style> - <style name="LockPatternStyle"> + <style name="LockPatternViewStyle" > <item name="*android:regularColor">?android:attr/colorAccent</item> <item name="*android:successColor">?android:attr/textColorPrimary</item> <item name="*android:errorColor">?android:attr/colorError</item> <item name="*android:dotColor">?android:attr/textColorSecondary</item> </style> - <style name="LockPatternStyleBiometricPrompt"> - <item name="*android:regularColor">?android:attr/colorForeground</item> - <item name="*android:successColor">?android:attr/colorForeground</item> - <item name="*android:errorColor">?android:attr/colorError</item> - <item name="*android:dotColor">?android:attr/textColorSecondary</item> + <style name="LockPatternContainerStyle" parent="@style/AuthCredentialStyle"> + <item name="containerStyle">@style/AuthCredentialPatternContainerStyle</item> + </style> + + <style name="LockPinPasswordContainerStyle" parent="@style/AuthCredentialStyle"> + <item name="containerStyle">@style/AuthCredentialPinPasswordContainerStyle</item> </style> <style name="Theme.SystemUI.QuickSettings" parent="@*android:style/Theme.DeviceDefault"> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt index 860a5da44088..1cf7c503a508 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt @@ -20,16 +20,15 @@ import android.annotation.ColorInt import android.annotation.FloatRange import android.annotation.IntRange import android.annotation.SuppressLint -import android.app.compat.ChangeIdStateCache.invalidate import android.content.Context import android.graphics.Canvas +import android.graphics.Rect import android.text.Layout import android.text.TextUtils import android.text.format.DateFormat import android.util.AttributeSet +import android.util.MathUtils import android.widget.TextView -import com.android.internal.R.attr.contentDescription -import com.android.internal.R.attr.format import com.android.internal.annotations.VisibleForTesting import com.android.systemui.animation.GlyphCallback import com.android.systemui.animation.Interpolators @@ -39,6 +38,8 @@ import java.io.PrintWriter import java.util.Calendar import java.util.Locale import java.util.TimeZone +import kotlin.math.max +import kotlin.math.min /** * Displays the time with the hour positioned above the minutes. (ie: 09 above 30 is 9:30) @@ -189,8 +190,13 @@ class AnimatableClockView @JvmOverloads constructor( override fun onDraw(canvas: Canvas) { lastDraw = getTimestamp() - // intentionally doesn't call super.onDraw here or else the text will be rendered twice - textAnimator?.draw(canvas) + // Use textAnimator to render text if animation is enabled. + // Otherwise default to using standard draw functions. + if (isAnimationEnabled) { + textAnimator?.draw(canvas) + } else { + super.onDraw(canvas) + } } override fun invalidate() { @@ -311,7 +317,24 @@ class AnimatableClockView @JvmOverloads constructor( ) } - private val glyphFilter: GlyphCallback? = null // Add text animation tweak here. + // The offset of each glyph from where it should be. + private var glyphOffsets = mutableListOf(0.0f, 0.0f, 0.0f, 0.0f) + + private var lastSeenAnimationProgress = 1.0f + + // If the animation is being reversed, the target offset for each glyph for the "stop". + private var animationCancelStartPosition = mutableListOf(0.0f, 0.0f, 0.0f, 0.0f) + private var animationCancelStopPosition = 0.0f + + // Whether the currently playing animation needed a stop (and thus, is shortened). + private var currentAnimationNeededStop = false + + private val glyphFilter: GlyphCallback = { positionedGlyph, _ -> + val offset = positionedGlyph.lineNo * DIGITS_PER_LINE + positionedGlyph.glyphIndex + if (offset < glyphOffsets.size) { + positionedGlyph.x += glyphOffsets[offset] + } + } /** * Set text style with an optional animation. @@ -345,6 +368,9 @@ class AnimatableClockView @JvmOverloads constructor( onAnimationEnd = onAnimationEnd ) textAnimator?.glyphFilter = glyphFilter + if (color != null && !isAnimationEnabled) { + setTextColor(color) + } } else { // when the text animator is set, update its start values onTextAnimatorInitialized = Runnable { @@ -359,6 +385,9 @@ class AnimatableClockView @JvmOverloads constructor( onAnimationEnd = onAnimationEnd ) textAnimator?.glyphFilter = glyphFilter + if (color != null && !isAnimationEnabled) { + setTextColor(color) + } } } } @@ -421,6 +450,124 @@ class AnimatableClockView @JvmOverloads constructor( pw.println(" time=$time") } + fun moveForSplitShade(fromRect: Rect, toRect: Rect, fraction: Float) { + // Do we need to cancel an in-flight animation? + // Need to also check against 0.0f here; we can sometimes get two calls with fraction == 0, + // which trips up the check otherwise. + if (lastSeenAnimationProgress != 1.0f && + lastSeenAnimationProgress != 0.0f && + fraction == 0.0f) { + // New animation, but need to stop the old one. Figure out where each glyph currently + // is in relation to the box position. After that, use the leading digit's current + // position as the stop target. + currentAnimationNeededStop = true + + // We assume that the current glyph offsets would be relative to the "from" position. + val moveAmount = toRect.left - fromRect.left + + // Remap the current glyph offsets to be relative to the new "end" position, and figure + // out the start/end positions for the stop animation. + for (i in 0 until NUM_DIGITS) { + glyphOffsets[i] = -moveAmount + glyphOffsets[i] + animationCancelStartPosition[i] = glyphOffsets[i] + } + + // Use the leading digit's offset as the stop position. + if (toRect.left > fromRect.left) { + // It _was_ moving left + animationCancelStopPosition = glyphOffsets[0] + } else { + // It was moving right + animationCancelStopPosition = glyphOffsets[1] + } + } + + // Is there a cancellation in progress? + if (currentAnimationNeededStop && fraction < ANIMATION_CANCELLATION_TIME) { + val animationStopProgress = MathUtils.constrainedMap( + 0.0f, 1.0f, 0.0f, ANIMATION_CANCELLATION_TIME, fraction + ) + + // One of the digits has already stopped. + val animationStopStep = 1.0f / (NUM_DIGITS - 1) + + for (i in 0 until NUM_DIGITS) { + val stopAmount = if (toRect.left > fromRect.left) { + // It was moving left (before flipping) + MOVE_LEFT_DELAYS[i] * animationStopStep + } else { + // It was moving right (before flipping) + MOVE_RIGHT_DELAYS[i] * animationStopStep + } + + // Leading digit stops immediately. + if (stopAmount == 0.0f) { + glyphOffsets[i] = animationCancelStopPosition + } else { + val actualStopAmount = MathUtils.constrainedMap( + 0.0f, 1.0f, 0.0f, stopAmount, animationStopProgress + ) + val easedProgress = MOVE_INTERPOLATOR.getInterpolation(actualStopAmount) + val glyphMoveAmount = + animationCancelStopPosition - animationCancelStartPosition[i] + glyphOffsets[i] = + animationCancelStartPosition[i] + glyphMoveAmount * easedProgress + } + } + } else { + // Normal part of the animation. + // Do we need to remap the animation progress to take account of the cancellation? + val actualFraction = if (currentAnimationNeededStop) { + MathUtils.constrainedMap( + 0.0f, 1.0f, ANIMATION_CANCELLATION_TIME, 1.0f, fraction + ) + } else { + fraction + } + + val digitFractions = (0 until NUM_DIGITS).map { + // The delay for each digit, in terms of fraction (i.e. the digit should not move + // during 0.0 - 0.1). + val initialDelay = if (toRect.left > fromRect.left) { + MOVE_RIGHT_DELAYS[it] * MOVE_DIGIT_STEP + } else { + MOVE_LEFT_DELAYS[it] * MOVE_DIGIT_STEP + } + + val f = MathUtils.constrainedMap( + 0.0f, 1.0f, + initialDelay, initialDelay + AVAILABLE_ANIMATION_TIME, + actualFraction + ) + MOVE_INTERPOLATOR.getInterpolation(max(min(f, 1.0f), 0.0f)) + } + + // Was there an animation halt? + val moveAmount = if (currentAnimationNeededStop) { + // Only need to animate over the remaining space if the animation was aborted. + -animationCancelStopPosition + } else { + toRect.left.toFloat() - fromRect.left.toFloat() + } + + for (i in 0 until NUM_DIGITS) { + glyphOffsets[i] = -moveAmount + (moveAmount * digitFractions[i]) + } + } + + invalidate() + + if (fraction == 1.0f) { + // Reset + currentAnimationNeededStop = false + } + + lastSeenAnimationProgress = fraction + + // Ensure that the actual clock container is always in the "end" position. + this.setLeftTopRightBottom(toRect.left, toRect.top, toRect.right, toRect.bottom) + } + // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often. // This is an optimization to ensure we only recompute the patterns when the inputs change. private object Patterns { @@ -458,5 +605,36 @@ class AnimatableClockView @JvmOverloads constructor( private const val APPEAR_ANIM_DURATION: Long = 350 private const val CHARGE_ANIM_DURATION_PHASE_0: Long = 500 private const val CHARGE_ANIM_DURATION_PHASE_1: Long = 1000 + + // Constants for the animation + private val MOVE_INTERPOLATOR = Interpolators.STANDARD + + // Calculate the positions of all of the digits... + // Offset each digit by, say, 0.1 + // This means that each digit needs to move over a slice of "fractions", i.e. digit 0 should + // move from 0.0 - 0.7, digit 1 from 0.1 - 0.8, digit 2 from 0.2 - 0.9, and digit 3 + // from 0.3 - 1.0. + private const val NUM_DIGITS = 4 + private const val DIGITS_PER_LINE = 2 + + // How much of "fraction" to spend on canceling the animation, if needed + private const val ANIMATION_CANCELLATION_TIME = 0.4f + + // Delays. Each digit's animation should have a slight delay, so we get a nice + // "stepping" effect. When moving right, the second digit of the hour should move first. + // When moving left, the first digit of the hour should move first. The lists encode + // the delay for each digit (hour[0], hour[1], minute[0], minute[1]), to be multiplied + // by delayMultiplier. + private val MOVE_LEFT_DELAYS = listOf(0, 1, 2, 3) + private val MOVE_RIGHT_DELAYS = listOf(1, 0, 3, 2) + + // How much delay to apply to each subsequent digit. This is measured in terms of "fraction" + // (i.e. a value of 0.1 would cause a digit to wait until fraction had hit 0.1, or 0.2 etc + // before moving). + private const val MOVE_DIGIT_STEP = 0.1f + + // Total available transition time for each digit, taking into account the step. If step is + // 0.1, then digit 0 would animate over 0.0 - 0.7, making availableTime 0.7. + private val AVAILABLE_ANIMATION_TIME = 1.0f - MOVE_DIGIT_STEP * (NUM_DIGITS - 1) } } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt index e3c21cca2263..cd272635905b 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt @@ -21,7 +21,6 @@ import android.os.Handler import android.os.UserHandle import android.provider.Settings import android.util.Log -import com.android.systemui.dagger.qualifiers.Main import com.android.internal.annotations.Keep import com.android.systemui.plugins.ClockController import com.android.systemui.plugins.ClockId @@ -31,7 +30,6 @@ import com.android.systemui.plugins.ClockProviderPlugin import com.android.systemui.plugins.PluginListener import com.android.systemui.shared.plugins.PluginManager import com.google.gson.Gson -import javax.inject.Inject private val TAG = ClockRegistry::class.simpleName private const val DEBUG = true @@ -43,13 +41,6 @@ open class ClockRegistry( val handler: Handler, defaultClockProvider: ClockProvider ) { - @Inject constructor( - context: Context, - pluginManager: PluginManager, - @Main handler: Handler, - defaultClockProvider: DefaultClockProvider - ) : this(context, pluginManager, handler, defaultClockProvider as ClockProvider) { } - // Usually this would be a typealias, but a SAM provides better java interop fun interface ClockChangeListener { fun onClockChanged() diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockController.kt index b88795157a43..6fd61daee6ff 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockController.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockController.kt @@ -16,6 +16,7 @@ package com.android.systemui.shared.clocks import android.content.Context import android.content.res.Resources import android.graphics.Color +import android.graphics.Rect import android.icu.text.NumberFormat import android.util.TypedValue import android.view.LayoutInflater @@ -130,6 +131,10 @@ class DefaultClockController( lp.topMargin = (-0.5f * view.bottom).toInt() view.setLayoutParams(lp) } + + fun moveForSplitShade(fromRect: Rect, toRect: Rect, fraction: Float) { + view.moveForSplitShade(fromRect, toRect, fraction) + } } inner class DefaultClockEvents : ClockEvents { @@ -209,6 +214,13 @@ class DefaultClockController( clocks.forEach { it.animateDoze(dozeState.isActive, !hasJumped) } } } + + override fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) { + largeClock.moveForSplitShade(fromRect, toRect, fraction) + } + + override val hasCustomPositionUpdatedAnimation: Boolean + get() = true } private class AnimationState( diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java index 72f8b7b09dca..40c8774d4f34 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java @@ -1,13 +1,16 @@ package com.android.systemui.shared.recents.utilities; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.view.Surface.ROTATION_180; +import static android.view.Surface.ROTATION_270; +import static android.view.Surface.ROTATION_90; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.RectF; -import android.view.Surface; import com.android.systemui.shared.recents.model.ThumbnailData; +import com.android.wm.shell.util.SplitBounds; /** * Utility class to position the thumbnail in the TaskView @@ -16,10 +19,26 @@ public class PreviewPositionHelper { public static final float MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT = 0.1f; + /** + * Specifies that a stage is positioned at the top half of the screen if + * in portrait mode or at the left half of the screen if in landscape mode. + * TODO(b/254378592): Remove after consolidation + */ + public static final int STAGE_POSITION_TOP_OR_LEFT = 0; + + /** + * Specifies that a stage is positioned at the bottom half of the screen if + * in portrait mode or at the right half of the screen if in landscape mode. + * TODO(b/254378592): Remove after consolidation + */ + public static final int STAGE_POSITION_BOTTOM_OR_RIGHT = 1; + // Contains the portion of the thumbnail that is unclipped when fullscreen progress = 1. private final RectF mClippedInsets = new RectF(); private final Matrix mMatrix = new Matrix(); private boolean mIsOrientationChanged; + private SplitBounds mSplitBounds; + private int mDesiredStagePosition; public Matrix getMatrix() { return mMatrix; @@ -33,6 +52,11 @@ public class PreviewPositionHelper { return mIsOrientationChanged; } + public void setSplitBounds(SplitBounds splitBounds, int desiredStagePosition) { + mSplitBounds = splitBounds; + mDesiredStagePosition = desiredStagePosition; + } + /** * Updates the matrix based on the provided parameters */ @@ -42,10 +66,19 @@ public class PreviewPositionHelper { boolean isRotated = false; boolean isOrientationDifferent; + float fullscreenTaskWidth = screenWidthPx; + if (mSplitBounds != null && !mSplitBounds.appsStackedVertically) { + // For landscape, scale the width + float taskPercent = mDesiredStagePosition == STAGE_POSITION_TOP_OR_LEFT + ? mSplitBounds.leftTaskPercent + : (1 - (mSplitBounds.leftTaskPercent + mSplitBounds.dividerWidthPercent)); + // Scale landscape width to that of actual screen + fullscreenTaskWidth = screenWidthPx * taskPercent; + } int thumbnailRotation = thumbnailData.rotation; int deltaRotate = getRotationDelta(currentRotation, thumbnailRotation); RectF thumbnailClipHint = new RectF(); - float canvasScreenRatio = canvasWidth / (float) screenWidthPx; + float canvasScreenRatio = canvasWidth / fullscreenTaskWidth; float scaledTaskbarSize = taskbarSize * canvasScreenRatio; thumbnailClipHint.bottom = isTablet ? scaledTaskbarSize : 0; @@ -180,7 +213,7 @@ public class PreviewPositionHelper { * portrait or vice versa, {@code false} otherwise */ private boolean isOrientationChange(int deltaRotation) { - return deltaRotation == Surface.ROTATION_90 || deltaRotation == Surface.ROTATION_270; + return deltaRotation == ROTATION_90 || deltaRotation == ROTATION_270; } private void setThumbnailRotation(int deltaRotate, Rect thumbnailPosition) { @@ -189,13 +222,13 @@ public class PreviewPositionHelper { mMatrix.setRotate(90 * deltaRotate); switch (deltaRotate) { /* Counter-clockwise */ - case Surface.ROTATION_90: + case ROTATION_90: translateX = thumbnailPosition.height(); break; - case Surface.ROTATION_270: + case ROTATION_270: translateY = thumbnailPosition.width(); break; - case Surface.ROTATION_180: + case ROTATION_180: translateX = thumbnailPosition.width(); translateY = thumbnailPosition.height(); break; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index 202134b699d7..35eecdf27f48 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -40,6 +40,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; +import com.android.systemui.plugins.ClockAnimations; import com.android.systemui.plugins.ClockController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.clocks.ClockRegistry; @@ -404,5 +405,10 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS clock.dump(pw); } } + + /** Gets the animations for the current clock. */ + public ClockAnimations getClockAnimations() { + return getClock().getAnimations(); + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index e9f06eddf261..784974778af5 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -20,6 +20,7 @@ import android.graphics.Rect; import android.util.Slog; import com.android.keyguard.KeyguardClockSwitch.ClockSize; +import com.android.systemui.plugins.ClockAnimations; import com.android.systemui.statusbar.notification.AnimatableProperty; import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.stack.AnimationProperties; @@ -232,4 +233,9 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV mView.setClipBounds(null); } } + + /** Gets the animations for the current clock. */ + public ClockAnimations getClockAnimations() { + return mKeyguardClockSwitchController.getClockAnimations(); + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 46e187e041e4..b54665a11a8c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2380,10 +2380,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab stopListeningForFace(FACE_AUTH_STOPPED_USER_INPUT_ON_BOUNCER); } - public boolean isFaceScanning() { - return mFaceRunningState == BIOMETRIC_STATE_RUNNING; - } - private void updateFaceListeningState(int action, @NonNull FaceAuthUiEvent faceAuthUiEvent) { // If this message exists, we should not authenticate again until this message is // consumed by the handler diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfoModule.java index c4be1ba53503..72a44bd198f2 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockModule.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockInfoModule.java @@ -21,9 +21,14 @@ import java.util.List; import dagger.Module; import dagger.Provides; -/** Dagger Module for clock package. */ +/** + * Dagger Module for clock package. + * + * @deprecated Migrate to ClockRegistry + */ @Module -public abstract class ClockModule { +@Deprecated +public abstract class ClockInfoModule { /** */ @Provides diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java new file mode 100644 index 000000000000..f43f559b4234 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java @@ -0,0 +1,45 @@ +/* + * 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.keyguard.dagger; + +import android.content.Context; +import android.os.Handler; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Application; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.shared.clocks.ClockRegistry; +import com.android.systemui.shared.clocks.DefaultClockProvider; +import com.android.systemui.shared.plugins.PluginManager; + +import dagger.Module; +import dagger.Provides; + +/** Dagger Module for clocks. */ +@Module +public abstract class ClockRegistryModule { + /** Provide the ClockRegistry as a singleton so that it is not instantiated more than once. */ + @Provides + @SysUISingleton + public static ClockRegistry getClockRegistry( + @Application Context context, + PluginManager pluginManager, + @Main Handler handler, + DefaultClockProvider defaultClockProvider) { + return new ClockRegistry(context, pluginManager, handler, defaultClockProvider); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/Dumpable.java b/packages/SystemUI/src/com/android/systemui/Dumpable.java index 652595100c0f..73fdce6c9045 100644 --- a/packages/SystemUI/src/com/android/systemui/Dumpable.java +++ b/packages/SystemUI/src/com/android/systemui/Dumpable.java @@ -30,7 +30,6 @@ public interface Dumpable { /** * Called when it's time to dump the internal state - * @param fd A file descriptor. * @param pw Where to write your dump to. * @param args Arguments. */ diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt index c5955860aebf..7002811c3c83 100644 --- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt @@ -123,7 +123,7 @@ class FaceScanningOverlay( } override fun enableShowProtection(show: Boolean) { - val showScanningAnimNow = keyguardUpdateMonitor.isFaceScanning && show + val showScanningAnimNow = keyguardUpdateMonitor.isFaceDetectionRunning && show if (showScanningAnimNow == showScanningAnim) { return } diff --git a/packages/SystemUI/src/com/android/systemui/ProtoDumpable.kt b/packages/SystemUI/src/com/android/systemui/ProtoDumpable.kt new file mode 100644 index 000000000000..4c3a7ff4e2eb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ProtoDumpable.kt @@ -0,0 +1,7 @@ +package com.android.systemui + +import com.android.systemui.dump.nano.SystemUIProtoDump + +interface ProtoDumpable : Dumpable { + fun dumpProto(systemUIProtoDump: SystemUIProtoDump, args: Array<String>) +} diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java index 7bcba3cc1c46..50e03992df49 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java @@ -121,6 +121,6 @@ public class SystemUIService extends Service { DumpHandler.PRIORITY_ARG_CRITICAL}; } - mDumpHandler.dump(pw, massagedArgs); + mDumpHandler.dump(fd, pw, massagedArgs); } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index d43e5d9d09cc..3b41a2d22380 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -626,17 +626,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, mUdfpsController.onAodInterrupt(screenX, screenY, major, minor); } - /** - * Cancel a fingerprint scan manually. This will get rid of the white circle on the udfps - * sensor area even if the user hasn't explicitly lifted their finger yet. - */ - public void onCancelUdfps() { - if (mUdfpsController == null) { - return; - } - mUdfpsController.onCancelUdfps(); - } - private void sendResultAndCleanUp(@DismissedReason int reason, @Nullable byte[] credentialAttestation) { if (mReceiver == null) { @@ -964,8 +953,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, } else { Log.w(TAG, "onBiometricError callback but dialog is gone"); } - - onCancelUdfps(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java index 0892612d1825..76cd3f4c4f1d 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPasswordView.java @@ -16,12 +16,21 @@ package com.android.systemui.biometrics; +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import static android.view.WindowInsets.Type.ime; + import android.annotation.NonNull; import android.content.Context; +import android.graphics.Insets; import android.os.UserHandle; import android.text.InputType; +import android.text.TextUtils; import android.util.AttributeSet; import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnApplyWindowInsetsListener; +import android.view.ViewGroup; +import android.view.WindowInsets; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.ImeAwareEditText; @@ -31,18 +40,24 @@ import com.android.internal.widget.LockPatternChecker; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockscreenCredential; import com.android.internal.widget.VerifyCredentialResponse; +import com.android.systemui.Dumpable; import com.android.systemui.R; +import java.io.PrintWriter; + /** * Pin and Password UI */ public class AuthCredentialPasswordView extends AuthCredentialView - implements TextView.OnEditorActionListener { + implements TextView.OnEditorActionListener, OnApplyWindowInsetsListener, Dumpable { private static final String TAG = "BiometricPrompt/AuthCredentialPasswordView"; private final InputMethodManager mImm; private ImeAwareEditText mPasswordField; + private ViewGroup mAuthCredentialHeader; + private ViewGroup mAuthCredentialInput; + private int mBottomInset = 0; public AuthCredentialPasswordView(Context context, AttributeSet attrs) { @@ -53,6 +68,9 @@ public class AuthCredentialPasswordView extends AuthCredentialView @Override protected void onFinishInflate() { super.onFinishInflate(); + + mAuthCredentialHeader = findViewById(R.id.auth_credential_header); + mAuthCredentialInput = findViewById(R.id.auth_credential_input); mPasswordField = findViewById(R.id.lockPassword); mPasswordField.setOnEditorActionListener(this); // TODO: De-dupe the logic with AuthContainerView @@ -66,6 +84,8 @@ public class AuthCredentialPasswordView extends AuthCredentialView } return true; }); + + setOnApplyWindowInsetsListener(this); } @Override @@ -127,4 +147,92 @@ public class AuthCredentialPasswordView extends AuthCredentialView mPasswordField.setText(""); } } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (mAuthCredentialInput == null || mAuthCredentialHeader == null || mSubtitleView == null + || mDescriptionView == null || mPasswordField == null || mErrorView == null) { + return; + } + + int inputLeftBound; + int inputTopBound; + int headerRightBound = right; + int headerTopBounds = top; + final int subTitleBottom = (mSubtitleView.getVisibility() == GONE) ? mTitleView.getBottom() + : mSubtitleView.getBottom(); + final int descBottom = (mDescriptionView.getVisibility() == GONE) ? subTitleBottom + : mDescriptionView.getBottom(); + if (getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) { + inputTopBound = (bottom - mAuthCredentialInput.getHeight()) / 2; + inputLeftBound = (right - left) / 2; + headerRightBound = inputLeftBound; + headerTopBounds -= Math.min(mIconView.getBottom(), mBottomInset); + } else { + inputTopBound = + descBottom + (bottom - descBottom - mAuthCredentialInput.getHeight()) / 2; + inputLeftBound = (right - left - mAuthCredentialInput.getWidth()) / 2; + } + + if (mDescriptionView.getBottom() > mBottomInset) { + mAuthCredentialHeader.layout(left, headerTopBounds, headerRightBound, bottom); + } + mAuthCredentialInput.layout(inputLeftBound, inputTopBound, right, bottom); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + final int newWidth = MeasureSpec.getSize(widthMeasureSpec); + final int newHeight = MeasureSpec.getSize(heightMeasureSpec) - mBottomInset; + + setMeasuredDimension(newWidth, newHeight); + + final int halfWidthSpec = MeasureSpec.makeMeasureSpec(getWidth() / 2, + MeasureSpec.AT_MOST); + final int fullHeightSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.UNSPECIFIED); + if (getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) { + measureChildren(halfWidthSpec, fullHeightSpec); + } else { + measureChildren(widthMeasureSpec, fullHeightSpec); + } + } + + @NonNull + @Override + public WindowInsets onApplyWindowInsets(@NonNull View v, WindowInsets insets) { + + final Insets bottomInset = insets.getInsets(ime()); + if (v instanceof AuthCredentialPasswordView && mBottomInset != bottomInset.bottom) { + mBottomInset = bottomInset.bottom; + if (mBottomInset > 0 + && getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE) { + mTitleView.setSingleLine(true); + mTitleView.setEllipsize(TextUtils.TruncateAt.MARQUEE); + mTitleView.setMarqueeRepeatLimit(-1); + // select to enable marquee unless a screen reader is enabled + mTitleView.setSelected(!mAccessibilityManager.isEnabled() + || !mAccessibilityManager.isTouchExplorationEnabled()); + } else { + mTitleView.setSingleLine(false); + mTitleView.setEllipsize(null); + // select to enable marquee unless a screen reader is enabled + mTitleView.setSelected(false); + } + requestLayout(); + } + return insets; + } + + @Override + public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { + pw.println(TAG + "State:"); + pw.println(" mBottomInset=" + mBottomInset); + pw.println(" mAuthCredentialHeader size=(" + mAuthCredentialHeader.getWidth() + "," + + mAuthCredentialHeader.getHeight()); + pw.println(" mAuthCredentialInput size=(" + mAuthCredentialInput.getWidth() + "," + + mAuthCredentialInput.getHeight()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java index 11498dbc0b83..f9e44a0c1724 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialPatternView.java @@ -93,7 +93,9 @@ public class AuthCredentialPatternView extends AuthCredentialView { @Override protected void onErrorTimeoutFinish() { super.onErrorTimeoutFinish(); - mLockPatternView.setEnabled(true); + // select to enable marquee unless a screen reader is enabled + mLockPatternView.setEnabled(!mAccessibilityManager.isEnabled() + || !mAccessibilityManager.isTouchExplorationEnabled()); } public AuthCredentialPatternView(Context context, AttributeSet attrs) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java index 4fa835e038ec..5958e6a436f1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthCredentialView.java @@ -30,7 +30,6 @@ import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.UserInfo; import android.graphics.drawable.Drawable; -import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.PromptInfo; import android.os.AsyncTask; import android.os.CountDownTimer; @@ -77,7 +76,7 @@ public abstract class AuthCredentialView extends LinearLayout { protected final Handler mHandler; protected final LockPatternUtils mLockPatternUtils; - private final AccessibilityManager mAccessibilityManager; + protected final AccessibilityManager mAccessibilityManager; private final UserManager mUserManager; private final DevicePolicyManager mDevicePolicyManager; @@ -86,10 +85,10 @@ public abstract class AuthCredentialView extends LinearLayout { private boolean mShouldAnimatePanel; private boolean mShouldAnimateContents; - private TextView mTitleView; - private TextView mSubtitleView; - private TextView mDescriptionView; - private ImageView mIconView; + protected TextView mTitleView; + protected TextView mSubtitleView; + protected TextView mDescriptionView; + protected ImageView mIconView; protected TextView mErrorView; protected @Utils.CredentialType int mCredentialType; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index a7648bffe503..d17f7878f5f3 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -786,7 +786,7 @@ public class UdfpsController implements DozeReceiver { // ACTION_UP/ACTION_CANCEL, we need to be careful about not letting the screen // accidentally remain in high brightness mode. As a mitigation, queue a call to // cancel the fingerprint scan. - mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelUdfps, + mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::cancelAodInterrupt, AOD_INTERRUPT_TIMEOUT_MILLIS); // using a hard-coded value for major and minor until it is available from the sensor onFingerDown(requestId, screenX, screenY, minor, major); @@ -813,26 +813,22 @@ public class UdfpsController implements DozeReceiver { } /** - * Cancel UDFPS affordances - ability to hide the UDFPS overlay before the user explicitly - * lifts their finger. Generally, this should be called on errors in the authentication flow. - * - * The sensor that triggers an AOD fingerprint interrupt (see onAodInterrupt) doesn't give - * ACTION_UP/ACTION_CANCEL events, so and AOD interrupt scan needs to be cancelled manually. + * The sensor that triggers {@link #onAodInterrupt} doesn't emit ACTION_UP or ACTION_CANCEL + * events, which means the fingerprint gesture created by the AOD interrupt needs to be + * cancelled manually. * This should be called when authentication either succeeds or fails. Failing to cancel the * scan will leave the display in the UDFPS mode until the user lifts their finger. On optical * sensors, this can result in illumination persisting for longer than necessary. */ - void onCancelUdfps() { + @VisibleForTesting + void cancelAodInterrupt() { if (!mIsAodInterruptActive) { return; } if (mOverlay != null && mOverlay.getOverlayView() != null) { onFingerUp(mOverlay.getRequestId(), mOverlay.getOverlayView()); } - if (mCancelAodTimeoutAction != null) { - mCancelAodTimeoutAction.run(); - mCancelAodTimeoutAction = null; - } + mCancelAodTimeoutAction = null; mIsAodInterruptActive = false; } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt index 66a521c30f47..7d0109686351 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt @@ -21,13 +21,18 @@ import android.annotation.UiThread import android.content.Context import android.graphics.PixelFormat import android.graphics.Rect -import android.hardware.biometrics.BiometricOverlayConstants +import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP +import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD +import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER +import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR import android.hardware.biometrics.BiometricOverlayConstants.ShowReason import android.hardware.fingerprint.FingerprintManager import android.hardware.fingerprint.IUdfpsOverlayControllerCallback +import android.os.Build import android.os.RemoteException +import android.provider.Settings import android.util.Log import android.util.RotationUtils import android.view.LayoutInflater @@ -38,6 +43,7 @@ import android.view.WindowManager import android.view.accessibility.AccessibilityManager import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener import androidx.annotation.LayoutRes +import androidx.annotation.VisibleForTesting import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator @@ -54,13 +60,16 @@ import com.android.systemui.util.time.SystemClock private const val TAG = "UdfpsControllerOverlay" +@VisibleForTesting +const val SETTING_REMOVE_ENROLLMENT_UI = "udfps_overlay_remove_enrollment_ui" + /** * Keeps track of the overlay state and UI resources associated with a single FingerprintService * request. This state can persist across configuration changes via the [show] and [hide] * methods. */ @UiThread -class UdfpsControllerOverlay( +class UdfpsControllerOverlay @JvmOverloads constructor( private val context: Context, fingerprintManager: FingerprintManager, private val inflater: LayoutInflater, @@ -82,7 +91,8 @@ class UdfpsControllerOverlay( @ShowReason val requestReason: Int, private val controllerCallback: IUdfpsOverlayControllerCallback, private val onTouch: (View, MotionEvent, Boolean) -> Boolean, - private val activityLaunchAnimator: ActivityLaunchAnimator + private val activityLaunchAnimator: ActivityLaunchAnimator, + private val isDebuggable: Boolean = Build.IS_DEBUGGABLE ) { /** The view, when [isShowing], or null. */ var overlayView: UdfpsView? = null @@ -102,18 +112,19 @@ class UdfpsControllerOverlay( gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS flags = (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS or - WindowManager.LayoutParams.FLAG_SPLIT_TOUCH) + WindowManager.LayoutParams.FLAG_SPLIT_TOUCH) privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY // Avoid announcing window title. accessibilityTitle = " " } /** A helper if the [requestReason] was due to enrollment. */ - val enrollHelper: UdfpsEnrollHelper? = if (requestReason.isEnrollmentReason()) { - UdfpsEnrollHelper(context, fingerprintManager, requestReason) - } else { - null - } + val enrollHelper: UdfpsEnrollHelper? = + if (requestReason.isEnrollmentReason() && !shouldRemoveEnrollmentUi()) { + UdfpsEnrollHelper(context, fingerprintManager, requestReason) + } else { + null + } /** If the overlay is currently showing. */ val isShowing: Boolean @@ -129,6 +140,17 @@ class UdfpsControllerOverlay( private var touchExplorationEnabled = false + private fun shouldRemoveEnrollmentUi(): Boolean { + if (isDebuggable) { + return Settings.Global.getInt( + context.contentResolver, + SETTING_REMOVE_ENROLLMENT_UI, + 0 /* def */ + ) != 0 + } + return false + } + /** Show the overlay or return false and do nothing if it is already showing. */ @SuppressLint("ClickableViewAccessibility") fun show(controller: UdfpsController, params: UdfpsOverlayParams): Boolean { @@ -183,7 +205,18 @@ class UdfpsControllerOverlay( view: UdfpsView, controller: UdfpsController ): UdfpsAnimationViewController<*>? { - return when (requestReason) { + val isEnrollment = when (requestReason) { + REASON_ENROLL_FIND_SENSOR, REASON_ENROLL_ENROLLING -> true + else -> false + } + + val filteredRequestReason = if (isEnrollment && shouldRemoveEnrollmentUi()) { + REASON_AUTH_OTHER + } else { + requestReason + } + + return when (filteredRequestReason) { REASON_ENROLL_FIND_SENSOR, REASON_ENROLL_ENROLLING -> { UdfpsEnrollViewController( @@ -198,7 +231,7 @@ class UdfpsControllerOverlay( overlayParams.scaleFactor ) } - BiometricOverlayConstants.REASON_AUTH_KEYGUARD -> { + REASON_AUTH_KEYGUARD -> { UdfpsKeyguardViewController( view.addUdfpsView(R.layout.udfps_keyguard_view), statusBarStateController, @@ -216,7 +249,7 @@ class UdfpsControllerOverlay( activityLaunchAnimator ) } - BiometricOverlayConstants.REASON_AUTH_BP -> { + REASON_AUTH_BP -> { // note: empty controller, currently shows no visual affordance UdfpsBpViewController( view.addUdfpsView(R.layout.udfps_bp_view), @@ -226,8 +259,8 @@ class UdfpsControllerOverlay( dumpManager ) } - BiometricOverlayConstants.REASON_AUTH_OTHER, - BiometricOverlayConstants.REASON_AUTH_SETTINGS -> { + REASON_AUTH_OTHER, + REASON_AUTH_SETTINGS -> { UdfpsFpmOtherViewController( view.addUdfpsView(R.layout.udfps_fpm_other_view), statusBarStateController, @@ -440,4 +473,4 @@ private fun Int.isEnrollmentReason() = private fun Int.isImportantForAccessibility() = this == REASON_ENROLL_FIND_SENSOR || this == REASON_ENROLL_ENROLLING || - this == BiometricOverlayConstants.REASON_AUTH_BP + this == REASON_AUTH_BP diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java index 3871248eccd5..858bac30880b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java @@ -44,9 +44,6 @@ public interface FalsingCollector { void onQsDown(); /** */ - void setQsExpanded(boolean expanded); - - /** */ boolean shouldEnforceBouncer(); /** */ diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java index 28aac051c66d..0b7d6ab5acf7 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java @@ -49,10 +49,6 @@ public class FalsingCollectorFake implements FalsingCollector { } @Override - public void setQsExpanded(boolean expanded) { - } - - @Override public boolean shouldEnforceBouncer() { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index f5f9655ef24b..da3d293d543b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -23,6 +23,8 @@ import android.hardware.biometrics.BiometricSourceType; import android.util.Log; import android.view.MotionEvent; +import androidx.annotation.VisibleForTesting; + import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.dagger.SysUISingleton; @@ -30,6 +32,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shade.ShadeExpansionStateManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; @@ -133,6 +136,7 @@ class FalsingCollectorImpl implements FalsingCollector { ProximitySensor proximitySensor, StatusBarStateController statusBarStateController, KeyguardStateController keyguardStateController, + ShadeExpansionStateManager shadeExpansionStateManager, BatteryController batteryController, DockManager dockManager, @Main DelayableExecutor mainExecutor, @@ -157,6 +161,8 @@ class FalsingCollectorImpl implements FalsingCollector { mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateCallback); + shadeExpansionStateManager.addQsExpansionListener(this::onQsExpansionChanged); + mBatteryController.addCallback(mBatteryListener); mDockManager.addListener(mDockEventListener); } @@ -193,8 +199,8 @@ class FalsingCollectorImpl implements FalsingCollector { public void onQsDown() { } - @Override - public void setQsExpanded(boolean expanded) { + @VisibleForTesting + void onQsExpansionChanged(Boolean expanded) { if (expanded) { unregisterSensors(); } else if (mSessionStarted) { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index d7638d663dc9..7e31626983e7 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -23,7 +23,8 @@ import android.service.dreams.IDreamManager; import androidx.annotation.Nullable; import com.android.internal.statusbar.IStatusBarService; -import com.android.keyguard.clock.ClockModule; +import com.android.keyguard.clock.ClockInfoModule; +import com.android.keyguard.dagger.ClockRegistryModule; import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.BootCompleteCache; import com.android.systemui.BootCompleteCacheImpl; @@ -120,7 +121,8 @@ import dagger.Provides; BiometricsModule.class, BouncerViewModule.class, ClipboardOverlayModule.class, - ClockModule.class, + ClockInfoModule.class, + ClockRegistryModule.class, CoroutinesModule.class, DreamModule.class, ControlsModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt index 5fdd198c19d7..c256e447056b 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt @@ -99,7 +99,7 @@ class FaceScanningProviderFactory @Inject constructor( } fun shouldShowFaceScanningAnim(): Boolean { - return canShowFaceScanningAnim() && keyguardUpdateMonitor.isFaceScanning + return canShowFaceScanningAnim() && keyguardUpdateMonitor.isFaceDetectionRunning } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt index 0e1bfba8aadb..f8e2566efeff 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt @@ -224,10 +224,14 @@ class DozeLogger @Inject constructor( }) } - fun logPulseDropped(from: String, state: DozeMachine.State) { + /** + * Log why a pulse was dropped and the current doze machine state. The state can be null + * if the DozeMachine is the middle of transitioning between states. + */ + fun logPulseDropped(from: String, state: DozeMachine.State?) { buffer.log(TAG, INFO, { str1 = from - str2 = state.name + str2 = state?.name }, { "Pulse dropped, cannot pulse from=$str1 state=$str2" }) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index ef454ffbdeb1..97a2179baa32 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -536,13 +536,13 @@ public class DozeTriggers implements DozeMachine.Part { return; } - if (!mAllowPulseTriggers || mDozeHost.isPulsePending() || !canPulse()) { + if (!mAllowPulseTriggers || mDozeHost.isPulsePending() || !canPulse(dozeState)) { if (!mAllowPulseTriggers) { mDozeLog.tracePulseDropped("requestPulse - !mAllowPulseTriggers"); } else if (mDozeHost.isPulsePending()) { mDozeLog.tracePulseDropped("requestPulse - pulsePending"); - } else if (!canPulse()) { - mDozeLog.tracePulseDropped("requestPulse", dozeState); + } else if (!canPulse(dozeState)) { + mDozeLog.tracePulseDropped("requestPulse - dozeState cannot pulse", dozeState); } runIfNotNull(onPulseSuppressedListener); return; @@ -559,15 +559,16 @@ public class DozeTriggers implements DozeMachine.Part { // not in pocket, continue pulsing final boolean isPulsePending = mDozeHost.isPulsePending(); mDozeHost.setPulsePending(false); - if (!isPulsePending || mDozeHost.isPulsingBlocked() || !canPulse()) { + if (!isPulsePending || mDozeHost.isPulsingBlocked() || !canPulse(dozeState)) { if (!isPulsePending) { mDozeLog.tracePulseDropped("continuePulseRequest - pulse no longer" + " pending, pulse was cancelled before it could start" + " transitioning to pulsing state."); } else if (mDozeHost.isPulsingBlocked()) { mDozeLog.tracePulseDropped("continuePulseRequest - pulsingBlocked"); - } else if (!canPulse()) { - mDozeLog.tracePulseDropped("continuePulseRequest", mMachine.getState()); + } else if (!canPulse(dozeState)) { + mDozeLog.tracePulseDropped("continuePulseRequest" + + " - doze state cannot pulse", dozeState); } runIfNotNull(onPulseSuppressedListener); return; @@ -582,10 +583,10 @@ public class DozeTriggers implements DozeMachine.Part { .ifPresent(uiEventEnum -> mUiEventLogger.log(uiEventEnum, getKeyguardSessionId())); } - private boolean canPulse() { - return mMachine.getState() == DozeMachine.State.DOZE - || mMachine.getState() == DozeMachine.State.DOZE_AOD - || mMachine.getState() == DozeMachine.State.DOZE_AOD_DOCKED; + private boolean canPulse(DozeMachine.State dozeState) { + return dozeState == DozeMachine.State.DOZE + || dozeState == DozeMachine.State.DOZE_AOD + || dozeState == DozeMachine.State.DOZE_AOD_DOCKED; } @Nullable diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt index 478f86169718..609bd76cf210 100644 --- a/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt @@ -24,8 +24,13 @@ import com.android.systemui.R import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_CRITICAL import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_HIGH import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_NORMAL +import com.android.systemui.dump.nano.SystemUIProtoDump import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager +import com.google.protobuf.nano.MessageNano +import java.io.BufferedOutputStream +import java.io.FileDescriptor +import java.io.FileOutputStream import java.io.PrintWriter import javax.inject.Inject import javax.inject.Provider @@ -100,7 +105,7 @@ class DumpHandler @Inject constructor( /** * Dump the diagnostics! Behavior can be controlled via [args]. */ - fun dump(pw: PrintWriter, args: Array<String>) { + fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) { Trace.beginSection("DumpManager#dump()") val start = SystemClock.uptimeMillis() @@ -111,10 +116,12 @@ class DumpHandler @Inject constructor( return } - when (parsedArgs.dumpPriority) { - PRIORITY_ARG_CRITICAL -> dumpCritical(pw, parsedArgs) - PRIORITY_ARG_NORMAL -> dumpNormal(pw, parsedArgs) - else -> dumpParameterized(pw, parsedArgs) + when { + parsedArgs.dumpPriority == PRIORITY_ARG_CRITICAL -> dumpCritical(pw, parsedArgs) + parsedArgs.dumpPriority == PRIORITY_ARG_NORMAL && !parsedArgs.proto -> { + dumpNormal(pw, parsedArgs) + } + else -> dumpParameterized(fd, pw, parsedArgs) } pw.println() @@ -122,7 +129,7 @@ class DumpHandler @Inject constructor( Trace.endSection() } - private fun dumpParameterized(pw: PrintWriter, args: ParsedArgs) { + private fun dumpParameterized(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) { when (args.command) { "bugreport-critical" -> dumpCritical(pw, args) "bugreport-normal" -> dumpNormal(pw, args) @@ -130,7 +137,13 @@ class DumpHandler @Inject constructor( "buffers" -> dumpBuffers(pw, args) "config" -> dumpConfig(pw) "help" -> dumpHelp(pw) - else -> dumpTargets(args.nonFlagArgs, pw, args) + else -> { + if (args.proto) { + dumpProtoTargets(args.nonFlagArgs, fd, args) + } else { + dumpTargets(args.nonFlagArgs, pw, args) + } + } } } @@ -160,6 +173,26 @@ class DumpHandler @Inject constructor( } } + private fun dumpProtoTargets( + targets: List<String>, + fd: FileDescriptor, + args: ParsedArgs + ) { + val systemUIProto = SystemUIProtoDump() + if (targets.isNotEmpty()) { + for (target in targets) { + dumpManager.dumpProtoTarget(target, systemUIProto, args.rawArgs) + } + } else { + dumpManager.dumpProtoDumpables(systemUIProto, args.rawArgs) + } + val buffer = BufferedOutputStream(FileOutputStream(fd)) + buffer.use { + it.write(MessageNano.toByteArray(systemUIProto)) + it.flush() + } + } + private fun dumpTargets( targets: List<String>, pw: PrintWriter, @@ -267,6 +300,7 @@ class DumpHandler @Inject constructor( } } } + PROTO -> pArgs.proto = true "-t", "--tail" -> { pArgs.tailLength = readArgument(iterator, arg) { it.toInt() @@ -278,6 +312,9 @@ class DumpHandler @Inject constructor( "-h", "--help" -> { pArgs.command = "help" } + // This flag is passed as part of the proto dump in Bug reports, we can ignore + // it because this is our default behavior. + "-a" -> {} else -> { throw ArgParseException("Unknown flag: $arg") } @@ -314,7 +351,7 @@ class DumpHandler @Inject constructor( const val PRIORITY_ARG_CRITICAL = "CRITICAL" const val PRIORITY_ARG_HIGH = "HIGH" const val PRIORITY_ARG_NORMAL = "NORMAL" - const val PROTO = "--sysui_proto" + const val PROTO = "--proto" } } @@ -338,6 +375,7 @@ private class ParsedArgs( var tailLength: Int = 0 var command: String? = null var listOnly = false + var proto = false } class ArgParseException(message: String) : Exception(message) diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt index dbca65122fcb..ae780896a7e2 100644 --- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt +++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt @@ -18,6 +18,8 @@ package com.android.systemui.dump import android.util.ArrayMap import com.android.systemui.Dumpable +import com.android.systemui.ProtoDumpable +import com.android.systemui.dump.nano.SystemUIProtoDump import com.android.systemui.plugins.log.LogBuffer import java.io.PrintWriter import javax.inject.Inject @@ -90,7 +92,7 @@ open class DumpManager @Inject constructor() { target: String, pw: PrintWriter, args: Array<String>, - tailLength: Int + tailLength: Int, ) { for (dumpable in dumpables.values) { if (dumpable.name.endsWith(target)) { @@ -107,6 +109,36 @@ open class DumpManager @Inject constructor() { } } + @Synchronized + fun dumpProtoTarget( + target: String, + protoDump: SystemUIProtoDump, + args: Array<String> + ) { + for (dumpable in dumpables.values) { + if (dumpable.dumpable is ProtoDumpable && dumpable.name.endsWith(target)) { + dumpProtoDumpable(dumpable.dumpable, protoDump, args) + return + } + } + } + + @Synchronized + fun dumpProtoDumpables( + systemUIProtoDump: SystemUIProtoDump, + args: Array<String> + ) { + for (dumpable in dumpables.values) { + if (dumpable.dumpable is ProtoDumpable) { + dumpProtoDumpable( + dumpable.dumpable, + systemUIProtoDump, + args + ) + } + } + } + /** * Dumps all registered dumpables to [pw] */ @@ -184,6 +216,14 @@ open class DumpManager @Inject constructor() { buffer.dumpable.dump(pw, tailLength) } + private fun dumpProtoDumpable( + protoDumpable: ProtoDumpable, + systemUIProtoDump: SystemUIProtoDump, + args: Array<String> + ) { + protoDumpable.dumpProto(systemUIProtoDump, args) + } + private fun canAssignToNameLocked(name: String, newDumpable: Any): Boolean { val existingDumpable = dumpables[name]?.dumpable ?: buffers[name]?.dumpable return existingDumpable == null || newDumpable == existingDumpable @@ -195,4 +235,4 @@ private data class RegisteredDumpable<T>( val dumpable: T ) -private const val TAG = "DumpManager"
\ No newline at end of file +private const val TAG = "DumpManager" diff --git a/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java b/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java index 0a41a56b5ecb..da983ab03a1d 100644 --- a/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java +++ b/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java @@ -51,6 +51,7 @@ public class SystemUIAuxiliaryDumpService extends Service { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { // Simulate the NORMAL priority arg being passed to us mDumpHandler.dump( + fd, pw, new String[] { DumpHandler.PRIORITY_ARG, DumpHandler.PRIORITY_ARG_NORMAL }); } diff --git a/packages/SystemUI/src/com/android/systemui/dump/sysui.proto b/packages/SystemUI/src/com/android/systemui/dump/sysui.proto new file mode 100644 index 000000000000..cd8c08aeb2dc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dump/sysui.proto @@ -0,0 +1,27 @@ +/* + * 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. + */ +syntax = "proto3"; + +package com.android.systemui.dump; + +import "frameworks/base/packages/SystemUI/src/com/android/systemui/qs/proto/tiles.proto"; + +option java_multiple_files = true; + +message SystemUIProtoDump { + repeated com.android.systemui.qs.QsTileState tiles = 1; +} + diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index 027187c889b4..c07958de7a41 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -61,10 +61,6 @@ public class Flags { public static final ResourceBooleanFlag NOTIFICATION_DRAG_TO_CONTENTS = new ResourceBooleanFlag(108, R.bool.config_notificationToContents); - // TODO(b/254512703): Tracking Bug - public static final ReleasedFlag REMOVE_UNRANKED_NOTIFICATIONS = - new ReleasedFlag(109); - // TODO(b/254512517): Tracking Bug public static final UnreleasedFlag FSI_REQUIRES_KEYGUARD = new UnreleasedFlag(110, true); @@ -112,7 +108,8 @@ public class Flags { new ResourceBooleanFlag(205, R.bool.config_enableFaceScanningAnimation); // TODO(b/254512676): Tracking Bug - public static final UnreleasedFlag LOCKSCREEN_CUSTOM_CLOCKS = new UnreleasedFlag(207); + public static final UnreleasedFlag LOCKSCREEN_CUSTOM_CLOCKS = + new UnreleasedFlag(207, /* teamfood = */ true); /** * Flag to enable the usage of the new bouncer data source. This is a refactor of and @@ -143,6 +140,12 @@ public class Flags { // TODO(b/254513102): Tracking Bug public static final ReleasedFlag USER_CONTROLLER_USES_INTERACTOR = new ReleasedFlag(211); + /** + * Whether the clock on a wide lock screen should use the new "stepping" animation for moving + * the digits when the clock moves. + */ + public static final UnreleasedFlag STEP_CLOCK_ANIMATION = new UnreleasedFlag(212); + /***************************************/ // 300 - power menu // TODO(b/254512600): Tracking Bug @@ -151,9 +154,6 @@ public class Flags { /***************************************/ // 400 - smartspace - // TODO(b/254513080): Tracking Bug - public static final ReleasedFlag SMARTSPACE_DEDUPING = - new ReleasedFlag(400); // TODO(b/254513100): Tracking Bug public static final ReleasedFlag SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED = @@ -207,14 +207,30 @@ public class Flags { public static final ReleasedFlag STATUS_BAR_LETTERBOX_APPEARANCE = new ReleasedFlag(603, false); - // TODO(b/254512623): Tracking Bug + /** + * @deprecated replaced by mobile and wifi specific flags. + * + * TODO(b/254512623): Tracking Bug + */ + @Deprecated public static final UnreleasedFlag NEW_STATUS_BAR_PIPELINE_BACKEND = new UnreleasedFlag(604, false); - // TODO(b/254512660): Tracking Bug + /** + * @deprecated replaced by mobile and wifi specific flags. + * + * TODO(b/254512660): Tracking Bug + */ + @Deprecated public static final UnreleasedFlag NEW_STATUS_BAR_PIPELINE_FRONTEND = new UnreleasedFlag(605, false); + public static final UnreleasedFlag NEW_STATUS_BAR_MOBILE_ICONS = + new UnreleasedFlag(606, false); + + public static final UnreleasedFlag NEW_STATUS_BAR_WIFI_ICON = + new UnreleasedFlag(607, false); + /***************************************/ // 700 - dialer/calls // TODO(b/254512734): Tracking Bug @@ -278,7 +294,7 @@ public class Flags { public static final ReleasedFlag ROUNDED_BOX_RIPPLE = new ReleasedFlag(1002); // TODO(b/254512525): Tracking Bug - public static final UnreleasedFlag REFACTORED_DOCK_SETUP = new UnreleasedFlag(1003, true); + public static final ReleasedFlag REFACTORED_DOCK_SETUP = new ReleasedFlag(1003); // 1100 - windowing @Keep @@ -363,6 +379,10 @@ public class Flags { // 1700 - clipboard public static final UnreleasedFlag CLIPBOARD_OVERLAY_REFACTOR = new UnreleasedFlag(1700); + // 1800 - shade container + public static final UnreleasedFlag LEAVE_SHADE_OPEN_FOR_BUGREPORT = + new UnreleasedFlag(1800, true); + // Pay no attention to the reflection behind the curtain. // ========================== Curtain ========================== // | | diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java index da5819a7f3bc..3ef5499237f1 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java @@ -116,6 +116,7 @@ import com.android.systemui.MultiListLayout; import com.android.systemui.MultiListLayout.MultiListAdapter; import com.android.systemui.animation.DialogCuj; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.animation.Expandable; import com.android.systemui.animation.Interpolators; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.colorextraction.SysuiColorExtractor; @@ -448,10 +449,11 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene * * @param keyguardShowing True if keyguard is showing * @param isDeviceProvisioned True if device is provisioned - * @param view The view from which we should animate the dialog when showing it + * @param expandable The expandable from which we should animate the dialog when + * showing it */ public void showOrHideDialog(boolean keyguardShowing, boolean isDeviceProvisioned, - @Nullable View view) { + @Nullable Expandable expandable) { mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; if (mDialog != null && mDialog.isShowing()) { @@ -463,7 +465,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mDialog.dismiss(); mDialog = null; } else { - handleShow(view); + handleShow(expandable); } } @@ -495,7 +497,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } } - protected void handleShow(@Nullable View view) { + protected void handleShow(@Nullable Expandable expandable) { awakenIfNecessary(); mDialog = createDialog(); prepareDialog(); @@ -507,10 +509,12 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene // Don't acquire soft keyboard focus, to avoid destroying state when capturing bugreports mDialog.getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM); - if (view != null) { - mDialogLaunchAnimator.showFromView(mDialog, view, - new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, - INTERACTION_JANK_TAG)); + DialogLaunchAnimator.Controller controller = + expandable != null ? expandable.dialogLaunchController( + new DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, + INTERACTION_JANK_TAG)) : null; + if (controller != null) { + mDialogLaunchAnimator.show(mDialog, controller); } else { mDialog.show(); } @@ -1016,8 +1020,9 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene Log.w(TAG, "Bugreport handler could not be launched"); mIActivityManager.requestInteractiveBugReport(); } - // Close shade so user sees the activity - mCentralSurfacesOptional.ifPresent(CentralSurfaces::collapseShade); + // Maybe close shade (depends on a flag) so user sees the activity + mCentralSurfacesOptional.ifPresent( + CentralSurfaces::collapseShadeForBugreport); } catch (RemoteException e) { } } @@ -1036,8 +1041,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mMetricsLogger.action(MetricsEvent.ACTION_BUGREPORT_FROM_POWER_MENU_FULL); mUiEventLogger.log(GlobalActionsEvent.GA_BUGREPORT_LONG_PRESS); mIActivityManager.requestFullBugReport(); - // Close shade so user sees the activity - mCentralSurfacesOptional.ifPresent(CentralSurfaces::collapseShade); + // Maybe close shade (depends on a flag) so user sees the activity + mCentralSurfacesOptional.ifPresent(CentralSurfaces::collapseShadeForBugreport); } catch (RemoteException e) { } return false; diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt index 482a1397642b..bb2b4419a80a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt @@ -52,6 +52,7 @@ import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.animation.DialogCuj import com.android.systemui.animation.DialogLaunchAnimator +import com.android.systemui.animation.Expandable import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background @@ -98,10 +99,10 @@ interface FgsManagerController { fun init() /** - * Show the foreground services dialog. The dialog will be expanded from [viewLaunchedFrom] if + * Show the foreground services dialog. The dialog will be expanded from [expandable] if * it's not `null`. */ - fun showDialog(viewLaunchedFrom: View?) + fun showDialog(expandable: Expandable?) /** Add a [OnNumberOfPackagesChangedListener]. */ fun addOnNumberOfPackagesChangedListener(listener: OnNumberOfPackagesChangedListener) @@ -367,7 +368,7 @@ class FgsManagerControllerImpl @Inject constructor( override fun shouldUpdateFooterVisibility() = dialog == null - override fun showDialog(viewLaunchedFrom: View?) { + override fun showDialog(expandable: Expandable?) { synchronized(lock) { if (dialog == null) { @@ -403,16 +404,18 @@ class FgsManagerControllerImpl @Inject constructor( } mainExecutor.execute { - viewLaunchedFrom - ?.let { - dialogLaunchAnimator.showFromView( - dialog, it, - cuj = DialogCuj( - InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, - INTERACTION_JANK_TAG - ) + val controller = + expandable?.dialogLaunchController( + DialogCuj( + InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, + INTERACTION_JANK_TAG, ) - } ?: dialog.show() + ) + if (controller != null) { + dialogLaunchAnimator.show(dialog, controller) + } else { + dialog.show() + } } backgroundExecutor.execute { diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt index 9d64781ef2e9..a9943e886339 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt @@ -32,6 +32,7 @@ import com.android.internal.logging.nano.MetricsProto import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator +import com.android.systemui.animation.Expandable import com.android.systemui.globalactions.GlobalActionsDialogLite import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager @@ -156,7 +157,7 @@ internal class FooterActionsController @Inject constructor( startSettingsActivity() } else if (v === powerMenuLite) { uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS) - globalActionsDialog?.showOrHideDialog(false, true, v) + globalActionsDialog?.showOrHideDialog(false, true, Expandable.fromView(powerMenuLite)) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java index 7511278e0919..b1b9dd721eaf 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFgsManagerFooter.java @@ -29,6 +29,7 @@ import android.widget.TextView; import androidx.annotation.Nullable; import com.android.systemui.R; +import com.android.systemui.animation.Expandable; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.qs.dagger.QSScope; @@ -130,7 +131,7 @@ public class QSFgsManagerFooter implements View.OnClickListener, @Override public void onClick(View view) { - mFgsManagerController.showDialog(mRootView); + mFgsManagerController.showDialog(Expandable.fromView(view)); } public void refreshState() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index 67bf3003deff..6c1e95645550 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -39,6 +39,7 @@ import androidx.annotation.Nullable; import com.android.internal.util.FrameworkStatsLog; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; +import com.android.systemui.animation.Expandable; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.common.shared.model.Icon; import com.android.systemui.dagger.qualifiers.Background; @@ -169,7 +170,7 @@ public class QSSecurityFooter extends ViewController<View> // TODO(b/242040009): Remove this. public void showDeviceMonitoringDialog() { - mQSSecurityFooterUtils.showDeviceMonitoringDialog(mContext, mView); + mQSSecurityFooterUtils.showDeviceMonitoringDialog(mContext, Expandable.fromView(mView)); } public void refreshState() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java index ae6ed2008a77..67bc76998597 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java @@ -75,6 +75,7 @@ import com.android.internal.jank.InteractionJankMonitor; import com.android.systemui.R; import com.android.systemui.animation.DialogCuj; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.animation.Expandable; import com.android.systemui.common.shared.model.ContentDescription; import com.android.systemui.common.shared.model.Icon; import com.android.systemui.dagger.SysUISingleton; @@ -190,8 +191,9 @@ public class QSSecurityFooterUtils implements DialogInterface.OnClickListener { } /** Show the device monitoring dialog. */ - public void showDeviceMonitoringDialog(Context quickSettingsContext, @Nullable View view) { - createDialog(quickSettingsContext, view); + public void showDeviceMonitoringDialog(Context quickSettingsContext, + @Nullable Expandable expandable) { + createDialog(quickSettingsContext, expandable); } /** @@ -440,7 +442,7 @@ public class QSSecurityFooterUtils implements DialogInterface.OnClickListener { } } - private void createDialog(Context quickSettingsContext, @Nullable View view) { + private void createDialog(Context quickSettingsContext, @Nullable Expandable expandable) { mShouldUseSettingsButton.set(false); mBgHandler.post(() -> { String settingsButtonText = getSettingsButton(); @@ -453,9 +455,12 @@ public class QSSecurityFooterUtils implements DialogInterface.OnClickListener { ? settingsButtonText : getNegativeButton(), this); mDialog.setView(dialogView); - if (view != null && view.isAggregatedVisible()) { - mDialogLaunchAnimator.showFromView(mDialog, view, new DialogCuj( - InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG)); + DialogLaunchAnimator.Controller controller = + expandable != null ? expandable.dialogLaunchController(new DialogCuj( + InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG)) + : null; + if (controller != null) { + mDialogLaunchAnimator.show(mDialog, controller); } else { mDialog.show(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index ac46c85c10a4..f37d66877069 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -34,10 +34,12 @@ import com.android.internal.logging.InstanceId; import com.android.internal.logging.InstanceIdSequence; import com.android.internal.logging.UiEventLogger; import com.android.systemui.Dumpable; +import com.android.systemui.ProtoDumpable; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; +import com.android.systemui.dump.nano.SystemUIProtoDump; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.qs.QSTile; @@ -48,6 +50,7 @@ import com.android.systemui.qs.external.TileLifecycleManager; import com.android.systemui.qs.external.TileServiceKey; import com.android.systemui.qs.external.TileServiceRequestController; import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.qs.nano.QsTileState; import com.android.systemui.settings.UserFileManager; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.plugins.PluginManager; @@ -59,16 +62,20 @@ import com.android.systemui.tuner.TunerService.Tunable; import com.android.systemui.util.leak.GarbageMonitor; import com.android.systemui.util.settings.SecureSettings; +import org.jetbrains.annotations.NotNull; + import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.Executor; import java.util.function.Predicate; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Provider; @@ -82,7 +89,7 @@ import javax.inject.Provider; * This class also provides the interface for adding/removing/changing tiles. */ @SysUISingleton -public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, Dumpable { +public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, ProtoDumpable { private static final String TAG = "QSTileHost"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final int MAX_QS_INSTANCE_ID = 1 << 20; @@ -671,4 +678,15 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D mTiles.values().stream().filter(obj -> obj instanceof Dumpable) .forEach(o -> ((Dumpable) o).dump(pw, args)); } + + @Override + public void dumpProto(@NotNull SystemUIProtoDump systemUIProtoDump, @NotNull String[] args) { + List<QsTileState> data = mTiles.values().stream() + .map(QSTile::getState) + .map(TileStateToProtoKt::toProto) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + systemUIProtoDump.tiles = data.toArray(new QsTileState[0]); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileStateToProto.kt b/packages/SystemUI/src/com/android/systemui/qs/TileStateToProto.kt new file mode 100644 index 000000000000..2c8a5a4981d0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/TileStateToProto.kt @@ -0,0 +1,51 @@ +/* + * 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.systemui.qs + +import android.service.quicksettings.Tile +import android.text.TextUtils +import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.qs.external.CustomTile +import com.android.systemui.qs.nano.QsTileState +import com.android.systemui.util.nano.ComponentNameProto + +fun QSTile.State.toProto(): QsTileState? { + if (TextUtils.isEmpty(spec)) return null + val state = QsTileState() + if (spec.startsWith(CustomTile.PREFIX)) { + val protoComponentName = ComponentNameProto() + val tileComponentName = CustomTile.getComponentFromSpec(spec) + protoComponentName.packageName = tileComponentName.packageName + protoComponentName.className = tileComponentName.className + state.componentName = protoComponentName + } else { + state.spec = spec + } + state.state = + when (this.state) { + Tile.STATE_UNAVAILABLE -> QsTileState.UNAVAILABLE + Tile.STATE_INACTIVE -> QsTileState.INACTIVE + Tile.STATE_ACTIVE -> QsTileState.ACTIVE + else -> QsTileState.UNAVAILABLE + } + label?.let { state.label = it.toString() } + secondaryLabel?.let { state.secondaryLabel = it.toString() } + if (this is QSTile.BooleanState) { + state.booleanState = value + } + return state +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt index cf9b41c25388..9ba3501c3434 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt @@ -23,13 +23,11 @@ import android.content.Intent import android.content.IntentFilter import android.os.UserHandle import android.provider.Settings -import android.view.View import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.MetricsLogger import com.android.internal.logging.UiEventLogger import com.android.internal.logging.nano.MetricsProto import com.android.internal.util.FrameworkStatsLog -import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.animation.Expandable import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton @@ -74,37 +72,27 @@ interface FooterActionsInteractor { val deviceMonitoringDialogRequests: Flow<Unit> /** - * Show the device monitoring dialog, expanded from [view]. - * - * Important: [view] must be associated to the same [Context] as the [Quick Settings fragment] - * [com.android.systemui.qs.QSFragment]. - */ - // TODO(b/230830644): Replace view by Expandable interface. - fun showDeviceMonitoringDialog(view: View) - - /** - * Show the device monitoring dialog. + * Show the device monitoring dialog, expanded from [expandable] if it's not null. * * Important: [quickSettingsContext] *must* be the [Context] associated to the [Quick Settings * fragment][com.android.systemui.qs.QSFragment]. */ - // TODO(b/230830644): Replace view by Expandable interface. - fun showDeviceMonitoringDialog(quickSettingsContext: Context) + fun showDeviceMonitoringDialog(quickSettingsContext: Context, expandable: Expandable?) /** Show the foreground services dialog. */ - // TODO(b/230830644): Replace view by Expandable interface. - fun showForegroundServicesDialog(view: View) + fun showForegroundServicesDialog(expandable: Expandable) /** Show the power menu dialog. */ - // TODO(b/230830644): Replace view by Expandable interface. - fun showPowerMenuDialog(globalActionsDialogLite: GlobalActionsDialogLite, view: View) + fun showPowerMenuDialog( + globalActionsDialogLite: GlobalActionsDialogLite, + expandable: Expandable, + ) /** Show the settings. */ fun showSettings(expandable: Expandable) /** Show the user switcher. */ - // TODO(b/230830644): Replace view by Expandable interface. - fun showUserSwitcher(view: View) + fun showUserSwitcher(context: Context, expandable: Expandable) } @SysUISingleton @@ -147,28 +135,32 @@ constructor( null, ) - override fun showDeviceMonitoringDialog(view: View) { - qsSecurityFooterUtils.showDeviceMonitoringDialog(view.context, view) - DevicePolicyEventLogger.createEvent( - FrameworkStatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED - ) - .write() - } - - override fun showDeviceMonitoringDialog(quickSettingsContext: Context) { - qsSecurityFooterUtils.showDeviceMonitoringDialog(quickSettingsContext, /* view= */ null) + override fun showDeviceMonitoringDialog( + quickSettingsContext: Context, + expandable: Expandable?, + ) { + qsSecurityFooterUtils.showDeviceMonitoringDialog(quickSettingsContext, expandable) + if (expandable != null) { + DevicePolicyEventLogger.createEvent( + FrameworkStatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED + ) + .write() + } } - override fun showForegroundServicesDialog(view: View) { - fgsManagerController.showDialog(view) + override fun showForegroundServicesDialog(expandable: Expandable) { + fgsManagerController.showDialog(expandable) } - override fun showPowerMenuDialog(globalActionsDialogLite: GlobalActionsDialogLite, view: View) { + override fun showPowerMenuDialog( + globalActionsDialogLite: GlobalActionsDialogLite, + expandable: Expandable, + ) { uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS) globalActionsDialogLite.showOrHideDialog( /* keyguardShowing= */ false, /* isDeviceProvisioned= */ true, - view, + expandable, ) } @@ -189,21 +181,21 @@ constructor( ) } - override fun showUserSwitcher(view: View) { + override fun showUserSwitcher(context: Context, expandable: Expandable) { if (!featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)) { - userSwitchDialogController.showDialog(view) + userSwitchDialogController.showDialog(context, expandable) return } val intent = - Intent(view.context, UserSwitcherActivity::class.java).apply { + Intent(context, UserSwitcherActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) } activityStarter.startActivity( intent, true /* dismissShade */, - ActivityLaunchAnimator.Controller.fromView(view, null), + expandable.activityLaunchController(), true /* showOverlockscreenwhenlocked */, UserHandle.SYSTEM, ) diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt index dd1ffcc9fa12..3e39c8ee62f1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt @@ -31,6 +31,7 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.R +import com.android.systemui.animation.Expandable import com.android.systemui.common.ui.binder.IconViewBinder import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.people.ui.view.PeopleViewBinder.bind @@ -125,7 +126,7 @@ object FooterActionsViewBinder { launch { viewModel.security.collect { security -> if (previousSecurity != security) { - bindSecurity(securityHolder, security) + bindSecurity(view.context, securityHolder, security) previousSecurity = security } } @@ -159,6 +160,7 @@ object FooterActionsViewBinder { } private fun bindSecurity( + quickSettingsContext: Context, securityHolder: TextButtonViewHolder, security: FooterActionsSecurityButtonViewModel?, ) { @@ -171,9 +173,12 @@ object FooterActionsViewBinder { // Make sure that the chevron is visible and that the button is clickable if there is a // listener. val chevron = securityHolder.chevron - if (security.onClick != null) { + val onClick = security.onClick + if (onClick != null) { securityView.isClickable = true - securityView.setOnClickListener(security.onClick) + securityView.setOnClickListener { + onClick(quickSettingsContext, Expandable.fromView(securityView)) + } chevron.isVisible = true } else { securityView.isClickable = false @@ -205,7 +210,9 @@ object FooterActionsViewBinder { foregroundServicesWithNumberView.isVisible = false foregroundServicesWithTextView.isVisible = true - foregroundServicesWithTextView.setOnClickListener(foregroundServices.onClick) + foregroundServicesWithTextView.setOnClickListener { + foregroundServices.onClick(Expandable.fromView(foregroundServicesWithTextView)) + } foregroundServicesWithTextHolder.text.text = foregroundServices.text foregroundServicesWithTextHolder.newDot.isVisible = foregroundServices.hasNewChanges } else { @@ -213,7 +220,9 @@ object FooterActionsViewBinder { foregroundServicesWithTextView.isVisible = false foregroundServicesWithNumberView.visibility = View.VISIBLE - foregroundServicesWithNumberView.setOnClickListener(foregroundServices.onClick) + foregroundServicesWithNumberView.setOnClickListener { + foregroundServices.onClick(Expandable.fromView(foregroundServicesWithTextView)) + } foregroundServicesWithNumberHolder.number.text = foregroundServicesCount.toString() foregroundServicesWithNumberHolder.number.contentDescription = foregroundServices.text foregroundServicesWithNumberHolder.newDot.isVisible = foregroundServices.hasNewChanges @@ -229,7 +238,7 @@ object FooterActionsViewBinder { } buttonView.setBackgroundResource(model.background) - buttonView.setOnClickListener(model.onClick) + buttonView.setOnClickListener { model.onClick(Expandable.fromView(buttonView)) } val icon = model.icon val iconView = button.icon diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt index 9b5f683d8dab..8d819dacba67 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt @@ -17,7 +17,7 @@ package com.android.systemui.qs.footer.ui.viewmodel import android.annotation.DrawableRes -import android.view.View +import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon /** @@ -29,7 +29,5 @@ data class FooterActionsButtonViewModel( val icon: Icon, val iconTint: Int?, @DrawableRes val background: Int, - // TODO(b/230830644): Replace View by an Expandable interface that can expand in either dialog - // or activity. - val onClick: (View) -> Unit, + val onClick: (Expandable) -> Unit, ) diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsForegroundServicesButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsForegroundServicesButtonViewModel.kt index 98b53cb0ed5a..ff8130d3e6ec 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsForegroundServicesButtonViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsForegroundServicesButtonViewModel.kt @@ -16,7 +16,7 @@ package com.android.systemui.qs.footer.ui.viewmodel -import android.view.View +import com.android.systemui.animation.Expandable /** A ViewModel for the foreground services button. */ data class FooterActionsForegroundServicesButtonViewModel( @@ -24,5 +24,5 @@ data class FooterActionsForegroundServicesButtonViewModel( val text: String, val displayText: Boolean, val hasNewChanges: Boolean, - val onClick: (View) -> Unit, + val onClick: (Expandable) -> Unit, ) diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsSecurityButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsSecurityButtonViewModel.kt index 98ab129fc9de..3450505f9f86 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsSecurityButtonViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsSecurityButtonViewModel.kt @@ -16,12 +16,13 @@ package com.android.systemui.qs.footer.ui.viewmodel -import android.view.View +import android.content.Context +import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon /** A ViewModel for the security button. */ data class FooterActionsSecurityButtonViewModel( val icon: Icon, val text: String, - val onClick: ((View) -> Unit)?, + val onClick: ((quickSettingsContext: Context, Expandable) -> Unit)?, ) diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt index d3c06f60bc90..dee6fadbc9cb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt @@ -18,7 +18,6 @@ package com.android.systemui.qs.footer.ui.viewmodel import android.content.Context import android.util.Log -import android.view.View import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner @@ -199,50 +198,51 @@ class FooterActionsViewModel( */ suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) { footerActionsInteractor.deviceMonitoringDialogRequests.collect { - footerActionsInteractor.showDeviceMonitoringDialog(quickSettingsContext) + footerActionsInteractor.showDeviceMonitoringDialog( + quickSettingsContext, + expandable = null, + ) } } - private fun onSecurityButtonClicked(view: View) { + private fun onSecurityButtonClicked(quickSettingsContext: Context, expandable: Expandable) { if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return } - footerActionsInteractor.showDeviceMonitoringDialog(view) + footerActionsInteractor.showDeviceMonitoringDialog(quickSettingsContext, expandable) } - private fun onForegroundServiceButtonClicked(view: View) { + private fun onForegroundServiceButtonClicked(expandable: Expandable) { if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return } - footerActionsInteractor.showForegroundServicesDialog(view) + footerActionsInteractor.showForegroundServicesDialog(expandable) } - private fun onUserSwitcherClicked(view: View) { + private fun onUserSwitcherClicked(expandable: Expandable) { if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return } - footerActionsInteractor.showUserSwitcher(view) + footerActionsInteractor.showUserSwitcher(context, expandable) } - // TODO(b/230830644): Replace View by an Expandable interface that can expand in either dialog - // or activity. - private fun onSettingsButtonClicked(view: View) { + private fun onSettingsButtonClicked(expandable: Expandable) { if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return } - footerActionsInteractor.showSettings(Expandable.fromView(view)) + footerActionsInteractor.showSettings(expandable) } - private fun onPowerButtonClicked(view: View) { + private fun onPowerButtonClicked(expandable: Expandable) { if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return } - footerActionsInteractor.showPowerMenuDialog(globalActionsDialogLite, view) + footerActionsInteractor.showPowerMenuDialog(globalActionsDialogLite, expandable) } private fun userSwitcherButton( diff --git a/packages/SystemUI/src/com/android/systemui/qs/proto/tiles.proto b/packages/SystemUI/src/com/android/systemui/qs/proto/tiles.proto new file mode 100644 index 000000000000..2a61033cb302 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/proto/tiles.proto @@ -0,0 +1,47 @@ +/* + * 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. + */ + +syntax = "proto3"; + +package com.android.systemui.qs; + +import "frameworks/base/packages/SystemUI/src/com/android/systemui/util/proto/component_name.proto"; + +option java_multiple_files = true; + +message QsTileState { + oneof identifier { + string spec = 1; + com.android.systemui.util.ComponentNameProto component_name = 2; + } + + enum State { + UNAVAILABLE = 0; + INACTIVE = 1; + ACTIVE = 2; + } + + State state = 3; + oneof optional_boolean_state { + bool boolean_state = 4; + } + oneof optional_label { + string label = 5; + } + oneof optional_secondary_label { + string secondary_label = 6; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt index bdcc6b0b2a57..314252bf310b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt @@ -23,13 +23,13 @@ import android.content.DialogInterface.BUTTON_NEUTRAL import android.content.Intent import android.provider.Settings import android.view.LayoutInflater -import android.view.View import androidx.annotation.VisibleForTesting import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.UiEventLogger import com.android.systemui.R import com.android.systemui.animation.DialogCuj import com.android.systemui.animation.DialogLaunchAnimator +import com.android.systemui.animation.Expandable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager @@ -77,10 +77,10 @@ class UserSwitchDialogController @VisibleForTesting constructor( * Show a [UserDialog]. * * Populate the dialog with information from and adapter obtained from - * [userDetailViewAdapterProvider] and show it as launched from [view]. + * [userDetailViewAdapterProvider] and show it as launched from [expandable]. */ - fun showDialog(view: View) { - with(dialogFactory(view.context)) { + fun showDialog(context: Context, expandable: Expandable) { + with(dialogFactory(context)) { setShowForAllUsers(true) setCanceledOnTouchOutside(true) @@ -112,13 +112,19 @@ class UserSwitchDialogController @VisibleForTesting constructor( adapter.linkToViewGroup(gridFrame.findViewById(R.id.grid)) - dialogLaunchAnimator.showFromView( - this, view, - cuj = DialogCuj( - InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, - INTERACTION_JANK_TAG + val controller = + expandable.dialogLaunchController( + DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG) ) - ) + if (controller != null) { + dialogLaunchAnimator.show( + this, + controller, + ) + } else { + show() + } + uiEventLogger.log(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN) adapter.injectDialogShower(DialogShowerImpl(this, dialogLaunchAnimator)) } diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index c1afd59a1e22..992163c86141 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -79,7 +79,10 @@ import android.os.UserManager; import android.os.VibrationEffect; import android.provider.Settings; import android.transition.ChangeBounds; +import android.transition.Transition; import android.transition.TransitionManager; +import android.transition.TransitionSet; +import android.transition.TransitionValues; import android.util.IndentingPrintWriter; import android.util.Log; import android.util.MathUtils; @@ -148,6 +151,8 @@ import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationBarController; +import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager.FalsingTapListener; @@ -580,6 +585,7 @@ public final class NotificationPanelViewController { private final SysUiState mSysUiState; private final NotificationShadeDepthController mDepthController; + private final NavigationBarController mNavigationBarController; private final int mDisplayId; private KeyguardIndicationController mKeyguardIndicationController; @@ -858,6 +864,7 @@ public final class NotificationPanelViewController { PrivacyDotViewController privacyDotViewController, TapAgainViewController tapAgainViewController, NavigationModeController navigationModeController, + NavigationBarController navigationBarController, FragmentService fragmentService, ContentResolver contentResolver, RecordingController recordingController, @@ -951,6 +958,7 @@ public final class NotificationPanelViewController { mNotificationsQSContainerController = notificationsQSContainerController; mNotificationListContainer = notificationListContainer; mNotificationStackSizeCalculator = notificationStackSizeCalculator; + mNavigationBarController = navigationBarController; mKeyguardBottomAreaViewControllerProvider = keyguardBottomAreaViewControllerProvider; mNotificationsQSContainerController.init(); mNotificationStackScrollLayoutController = notificationStackScrollLayoutController; @@ -1440,6 +1448,16 @@ public final class NotificationPanelViewController { mMaxAllowedKeyguardNotifications = maxAllowed; } + @VisibleForTesting + boolean getClosing() { + return mClosing; + } + + @VisibleForTesting + boolean getIsFlinging() { + return mIsFlinging; + } + private void updateMaxDisplayedNotifications(boolean recompute) { if (recompute) { setMaxDisplayedNotifications(Math.max(computeMaxKeyguardNotifications(), 1)); @@ -1667,9 +1685,40 @@ public final class NotificationPanelViewController { // horizontally properly. transition.excludeTarget(R.id.status_view_media_container, true); } + transition.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); transition.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); - TransitionManager.beginDelayedTransition(mNotificationContainerParent, transition); + + boolean customClockAnimation = + mKeyguardStatusViewController.getClockAnimations() != null + && mKeyguardStatusViewController.getClockAnimations() + .getHasCustomPositionUpdatedAnimation(); + + if (mFeatureFlags.isEnabled(Flags.STEP_CLOCK_ANIMATION) && customClockAnimation) { + // Find the clock, so we can exclude it from this transition. + FrameLayout clockContainerView = + mView.findViewById(R.id.lockscreen_clock_view_large); + View clockView = clockContainerView.getChildAt(0); + + transition.excludeTarget(clockView, /* exclude= */ true); + + TransitionSet set = new TransitionSet(); + set.addTransition(transition); + + SplitShadeTransitionAdapter adapter = + new SplitShadeTransitionAdapter(mKeyguardStatusViewController); + + // Use linear here, so the actual clock can pick its own interpolator. + adapter.setInterpolator(Interpolators.LINEAR); + adapter.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); + adapter.addTarget(clockView); + set.addTransition(adapter); + + TransitionManager.beginDelayedTransition(mNotificationContainerParent, set); + } else { + TransitionManager.beginDelayedTransition( + mNotificationContainerParent, transition); + } } constraintSet.applyTo(mNotificationContainerParent); @@ -2637,12 +2686,16 @@ public final class NotificationPanelViewController { mQsExpanded = expanded; updateQsState(); updateExpandedHeightToMaxHeight(); - mFalsingCollector.setQsExpanded(expanded); - mCentralSurfaces.setQsExpanded(expanded); - mNotificationsQSContainerController.setQsExpanded(expanded); - mPulseExpansionHandler.setQsExpanded(expanded); - mKeyguardBypassController.setQSExpanded(expanded); - mPrivacyDotViewController.setQsExpanded(expanded); + setStatusAccessibilityImportance(expanded + ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS + : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + updateSystemUiStateFlags(); + NavigationBarView navigationBarView = + mNavigationBarController.getNavigationBarView(mDisplayId); + if (navigationBarView != null) { + navigationBarView.onStatusBarPanelStateChanged(); + } + mShadeExpansionStateManager.onQsExpansionChanged(expanded); } } @@ -3684,6 +3737,11 @@ public final class NotificationPanelViewController { setListening(true); } + @VisibleForTesting + void setTouchSlopExceeded(boolean isTouchSlopExceeded) { + mTouchSlopExceeded = isTouchSlopExceeded; + } + public void setOverExpansion(float overExpansion) { if (overExpansion == mOverExpansion) { return; @@ -4166,8 +4224,8 @@ public final class NotificationPanelViewController { /** * Sets the dozing state. * - * @param dozing {@code true} when dozing. - * @param animate if transition should be animated. + * @param dozing {@code true} when dozing. + * @param animate if transition should be animated. */ public void setDozing(boolean dozing, boolean animate) { if (dozing == mDozing) return; @@ -4307,35 +4365,35 @@ public final class NotificationPanelViewController { /** * Starts fold to AOD animation. * - * @param startAction invoked when the animation starts. - * @param endAction invoked when the animation finishes, also if it was cancelled. + * @param startAction invoked when the animation starts. + * @param endAction invoked when the animation finishes, also if it was cancelled. * @param cancelAction invoked when the animation is cancelled, before endAction. */ public void startFoldToAodAnimation(Runnable startAction, Runnable endAction, Runnable cancelAction) { mView.animate() - .translationX(0) - .alpha(1f) - .setDuration(ANIMATION_DURATION_FOLD_TO_AOD) - .setInterpolator(EMPHASIZED_DECELERATE) - .setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - startAction.run(); - } + .translationX(0) + .alpha(1f) + .setDuration(ANIMATION_DURATION_FOLD_TO_AOD) + .setInterpolator(EMPHASIZED_DECELERATE) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + startAction.run(); + } - @Override - public void onAnimationCancel(Animator animation) { - cancelAction.run(); - } + @Override + public void onAnimationCancel(Animator animation) { + cancelAction.run(); + } - @Override - public void onAnimationEnd(Animator animation) { - endAction.run(); - } - }).setUpdateListener(anim -> { - mKeyguardStatusViewController.animateFoldToAod(anim.getAnimatedFraction()); - }).start(); + @Override + public void onAnimationEnd(Animator animation) { + endAction.run(); + } + }).setUpdateListener(anim -> { + mKeyguardStatusViewController.animateFoldToAod(anim.getAnimatedFraction()); + }).start(); } /** @@ -4695,8 +4753,10 @@ public final class NotificationPanelViewController { /** * Maybe vibrate as panel is opened. * - * @param openingWithTouch Whether the panel is being opened with touch. If the panel is instead - * being opened programmatically (such as by the open panel gesture), we always play haptic. + * @param openingWithTouch Whether the panel is being opened with touch. If the panel is + * instead + * being opened programmatically (such as by the open panel gesture), we + * always play haptic. */ private void maybeVibrateOnOpening(boolean openingWithTouch) { if (mVibrateOnOpening) { @@ -4742,6 +4802,7 @@ public final class NotificationPanelViewController { mAmbientState.setSwipingUp(false); if ((mTracking && mTouchSlopExceeded) || Math.abs(x - mInitialExpandX) > mTouchSlop || Math.abs(y - mInitialExpandY) > mTouchSlop + || (!isFullyExpanded() && !isFullyCollapsed()) || event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel) { mVelocityTracker.computeCurrentVelocity(1000); float vel = mVelocityTracker.getYVelocity(); @@ -4861,10 +4922,12 @@ public final class NotificationPanelViewController { animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); animator.addListener(new AnimatorListenerAdapter() { private boolean mCancelled; + @Override public void onAnimationCancel(Animator animation) { mCancelled = true; } + @Override public void onAnimationEnd(Animator animation) { mIsSpringBackAnimation = false; @@ -4912,7 +4975,7 @@ public final class NotificationPanelViewController { if (isNaN(h)) { Log.wtf(TAG, "ExpandedHeight set to NaN"); } - mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + mNotificationShadeWindowController.batchApplyWindowLayoutParams(() -> { if (mExpandLatencyTracking && h != 0f) { DejankUtils.postAfterTraversal( () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL)); @@ -5103,7 +5166,7 @@ public final class NotificationPanelViewController { /** * Create an animator that can also overshoot * - * @param targetHeight the target height + * @param targetHeight the target height * @param overshootAmount the amount of overshoot desired */ private ValueAnimator createHeightAnimator(float targetHeight, float overshootAmount) { @@ -5139,7 +5202,8 @@ public final class NotificationPanelViewController { */ public void updatePanelExpansionAndVisibility() { mShadeExpansionStateManager.onPanelExpansionChanged( - mExpandedFraction, isExpanded(), mTracking, mExpansionDragDownAmountPx); + mExpandedFraction, isExpanded(), + mTracking, mExpansionDragDownAmountPx); updateVisibility(); } @@ -5900,7 +5964,7 @@ public final class NotificationPanelViewController { public final class TouchHandler implements View.OnTouchListener { private long mLastTouchDownTime = -1L; - /** @see ViewGroup#onInterceptTouchEvent(MotionEvent) */ + /** @see ViewGroup#onInterceptTouchEvent(MotionEvent) */ public boolean onInterceptTouchEvent(MotionEvent event) { if (SPEW_LOGCAT) { Log.v(TAG, @@ -6099,7 +6163,7 @@ public final class NotificationPanelViewController { mShadeLog.logMotionEvent(event, "onTouch: touch ignored due to instant expanding"); return false; } - if (mTouchDisabled && event.getActionMasked() != MotionEvent.ACTION_CANCEL) { + if (mTouchDisabled && event.getActionMasked() != MotionEvent.ACTION_CANCEL) { mShadeLog.logMotionEvent(event, "onTouch: non-cancel action, touch disabled"); return false; } @@ -6256,4 +6320,54 @@ public final class NotificationPanelViewController { loadDimens(); } } + + static class SplitShadeTransitionAdapter extends Transition { + private static final String PROP_BOUNDS = "splitShadeTransitionAdapter:bounds"; + private static final String[] TRANSITION_PROPERTIES = { PROP_BOUNDS }; + + private final KeyguardStatusViewController mController; + + SplitShadeTransitionAdapter(KeyguardStatusViewController controller) { + mController = controller; + } + + private void captureValues(TransitionValues transitionValues) { + Rect boundsRect = new Rect(); + boundsRect.left = transitionValues.view.getLeft(); + boundsRect.top = transitionValues.view.getTop(); + boundsRect.right = transitionValues.view.getRight(); + boundsRect.bottom = transitionValues.view.getBottom(); + transitionValues.values.put(PROP_BOUNDS, boundsRect); + } + + @Override + public void captureEndValues(TransitionValues transitionValues) { + captureValues(transitionValues); + } + + @Override + public void captureStartValues(TransitionValues transitionValues) { + captureValues(transitionValues); + } + + @Override + public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, + TransitionValues endValues) { + ValueAnimator anim = ValueAnimator.ofFloat(0, 1); + + Rect from = (Rect) startValues.values.get(PROP_BOUNDS); + Rect to = (Rect) endValues.values.get(PROP_BOUNDS); + + anim.addUpdateListener( + animation -> mController.getClockAnimations().onPositionUpdated( + from, to, animation.getAnimatedFraction())); + + return anim; + } + + @Override + public String[] getTransitionProperties() { + return TRANSITION_PROPERTIES; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java index 1d9210592b78..66a22f4ddc0d 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java @@ -135,7 +135,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW DumpManager dumpManager, KeyguardStateController keyguardStateController, ScreenOffAnimationController screenOffAnimationController, - AuthController authController) { + AuthController authController, + ShadeExpansionStateManager shadeExpansionStateManager) { mContext = context; mWindowManager = windowManager; mActivityManager = activityManager; @@ -156,6 +157,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW .addCallback(mStateListener, SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER); configurationController.addCallback(this); + shadeExpansionStateManager.addQsExpansionListener(this::onQsExpansionChanged); float desiredPreferredRefreshRate = context.getResources() .getInteger(R.integer.config_keyguardRefreshRate); @@ -607,8 +609,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW apply(mCurrentState); } - @Override - public void setQsExpanded(boolean expanded) { + private void onQsExpansionChanged(Boolean expanded) { mCurrentState.mQsExpanded = expanded; apply(mCurrentState); } diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt index d6f0de83ecc1..73c6d507f035 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt @@ -36,17 +36,12 @@ class NotificationsQSContainerController @Inject constructor( private val navigationModeController: NavigationModeController, private val overviewProxyService: OverviewProxyService, private val largeScreenShadeHeaderController: LargeScreenShadeHeaderController, + private val shadeExpansionStateManager: ShadeExpansionStateManager, private val featureFlags: FeatureFlags, @Main private val delayableExecutor: DelayableExecutor ) : ViewController<NotificationsQuickSettingsContainer>(view), QSContainerController { - var qsExpanded = false - set(value) { - if (field != value) { - field = value - mView.invalidate() - } - } + private var qsExpanded = false private var splitShadeEnabled = false private var isQSDetailShowing = false private var isQSCustomizing = false @@ -71,6 +66,13 @@ class NotificationsQSContainerController @Inject constructor( taskbarVisible = visible } } + private val shadeQsExpansionListener: ShadeQsExpansionListener = + ShadeQsExpansionListener { isQsExpanded -> + if (qsExpanded != isQsExpanded) { + qsExpanded = isQsExpanded + mView.invalidate() + } + } // With certain configuration changes (like light/dark changes), the nav bar will disappear // for a bit, causing `bottomStableInsets` to be unstable for some time. Debounce the value @@ -106,6 +108,7 @@ class NotificationsQSContainerController @Inject constructor( public override fun onViewAttached() { updateResources() overviewProxyService.addCallback(taskbarVisibilityListener) + shadeExpansionStateManager.addQsExpansionListener(shadeQsExpansionListener) mView.setInsetsChangedListener(delayedInsetSetter) mView.setQSFragmentAttachedListener { qs: QS -> qs.setContainerController(this) } mView.setConfigurationChangedListener { updateResources() } @@ -113,6 +116,7 @@ class NotificationsQSContainerController @Inject constructor( override fun onViewDetached() { overviewProxyService.removeCallback(taskbarVisibilityListener) + shadeExpansionStateManager.removeQsExpansionListener(shadeQsExpansionListener) mView.removeOnInsetsChangedListener() mView.removeQSFragmentAttachedListener() mView.setConfigurationChangedListener(null) diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt index f617d471351e..7bba74a8b125 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt @@ -21,6 +21,7 @@ import android.util.Log import androidx.annotation.FloatRange import com.android.systemui.dagger.SysUISingleton import com.android.systemui.util.Compile +import java.util.concurrent.CopyOnWriteArrayList import javax.inject.Inject /** @@ -31,12 +32,14 @@ import javax.inject.Inject @SysUISingleton class ShadeExpansionStateManager @Inject constructor() { - private val expansionListeners = mutableListOf<ShadeExpansionListener>() - private val stateListeners = mutableListOf<ShadeStateListener>() + private val expansionListeners = CopyOnWriteArrayList<ShadeExpansionListener>() + private val qsExpansionListeners = CopyOnWriteArrayList<ShadeQsExpansionListener>() + private val stateListeners = CopyOnWriteArrayList<ShadeStateListener>() @PanelState private var state: Int = STATE_CLOSED @FloatRange(from = 0.0, to = 1.0) private var fraction: Float = 0f private var expanded: Boolean = false + private var qsExpanded: Boolean = false private var tracking: Boolean = false private var dragDownPxAmount: Float = 0f @@ -57,6 +60,15 @@ class ShadeExpansionStateManager @Inject constructor() { expansionListeners.remove(listener) } + fun addQsExpansionListener(listener: ShadeQsExpansionListener) { + qsExpansionListeners.add(listener) + listener.onQsExpansionChanged(qsExpanded) + } + + fun removeQsExpansionListener(listener: ShadeQsExpansionListener) { + qsExpansionListeners.remove(listener) + } + /** Adds a listener that will be notified when the panel state has changed. */ fun addStateListener(listener: ShadeStateListener) { stateListeners.add(listener) @@ -126,6 +138,14 @@ class ShadeExpansionStateManager @Inject constructor() { expansionListeners.forEach { it.onPanelExpansionChanged(expansionChangeEvent) } } + /** Called when the quick settings expansion changes to fully expanded or collapsed. */ + fun onQsExpansionChanged(qsExpanded: Boolean) { + this.qsExpanded = qsExpanded + + debugLog("qsExpanded=$qsExpanded") + qsExpansionListeners.forEach { it.onQsExpansionChanged(qsExpanded) } + } + /** Updates the panel state if necessary. */ fun updateState(@PanelState state: Int) { debugLog( diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeQsExpansionListener.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeQsExpansionListener.kt new file mode 100644 index 000000000000..14882b9afd2f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeQsExpansionListener.kt @@ -0,0 +1,25 @@ +/* + * 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.systemui.shade + +/** A listener interface to be notified of expansion events for the quick settings panel. */ +fun interface ShadeQsExpansionListener { + /** + * Invoked whenever the quick settings expansion changes, when it is fully collapsed or expanded + */ + fun onQsExpansionChanged(isQsExpanded: Boolean) +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 04621168493b..e6d7e4124d01 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -69,12 +69,15 @@ import com.android.internal.statusbar.LetterboxDetails; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.util.GcUtils; import com.android.internal.view.AppearanceRegion; +import com.android.systemui.dump.DumpHandler; import com.android.systemui.statusbar.CommandQueue.Callbacks; import com.android.systemui.statusbar.commandline.CommandRegistry; import com.android.systemui.statusbar.policy.CallbackController; import com.android.systemui.tracing.ProtoTracer; +import java.io.FileDescriptor; import java.io.FileOutputStream; +import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; @@ -184,6 +187,7 @@ public class CommandQueue extends IStatusBar.Stub implements private int mLastUpdatedImeDisplayId = INVALID_DISPLAY; private ProtoTracer mProtoTracer; private final @Nullable CommandRegistry mRegistry; + private final @Nullable DumpHandler mDumpHandler; /** * These methods are called back on the main thread. @@ -473,12 +477,18 @@ public class CommandQueue extends IStatusBar.Stub implements } public CommandQueue(Context context) { - this(context, null, null); + this(context, null, null, null); } - public CommandQueue(Context context, ProtoTracer protoTracer, CommandRegistry registry) { + public CommandQueue( + Context context, + ProtoTracer protoTracer, + CommandRegistry registry, + DumpHandler dumpHandler + ) { mProtoTracer = protoTracer; mRegistry = registry; + mDumpHandler = dumpHandler; context.getSystemService(DisplayManager.class).registerDisplayListener(this, mHandler); // We always have default display. setDisabled(DEFAULT_DISPLAY, DISABLE_NONE, DISABLE2_NONE); @@ -1178,6 +1188,35 @@ public class CommandQueue extends IStatusBar.Stub implements } @Override + public void dumpProto(String[] args, ParcelFileDescriptor pfd) { + final FileDescriptor fd = pfd.getFileDescriptor(); + // This is mimicking Binder#dumpAsync, but on this side of the binder. Might be possible + // to just throw this work onto the handler just like the other messages + Thread thr = new Thread("Sysui.dumpProto") { + public void run() { + try { + if (mDumpHandler == null) { + return; + } + // We won't be using the PrintWriter. + OutputStream o = new OutputStream() { + @Override + public void write(int b) {} + }; + mDumpHandler.dump(fd, new PrintWriter(o), args); + } finally { + try { + // Close the file descriptor so the TransferPipe finishes its thread + pfd.close(); + } catch (Exception e) { + } + } + } + }; + thr.start(); + } + + @Override public void runGcForTest() { // Gc sysui GcUtils.runGcAndFinalizersSync(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java index 0c9e1ec1ff77..e21acb7e0f68 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java @@ -92,9 +92,6 @@ public interface NotificationShadeWindowController extends RemoteInputController /** Sets the state of whether the keyguard is fading away or not. */ default void setKeyguardFadingAway(boolean keyguardFadingAway) {} - /** Sets the state of whether the quick settings is expanded or not. */ - default void setQsExpanded(boolean expanded) {} - /** Sets the state of whether the user activities are forced or not. */ default void setForceUserActivity(boolean forceUserActivity) {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt index 8222c9d9ba59..c630feba1dcb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt @@ -39,6 +39,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.shade.ShadeExpansionStateManager import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.ExpandableView @@ -68,6 +69,7 @@ constructor( configurationController: ConfigurationController, private val statusBarStateController: StatusBarStateController, private val falsingManager: FalsingManager, + shadeExpansionStateManager: ShadeExpansionStateManager, private val lockscreenShadeTransitionController: LockscreenShadeTransitionController, private val falsingCollector: FalsingCollector, dumpManager: DumpManager @@ -126,6 +128,13 @@ constructor( initResources(context) } }) + + shadeExpansionStateManager.addQsExpansionListener { isQsExpanded -> + if (qsExpanded != isQsExpanded) { + qsExpanded = isQsExpanded + } + } + mPowerManager = context.getSystemService(PowerManager::class.java) dumpManager.registerDumpable(this) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java index 11e3d1773c4c..f574be056109 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java @@ -29,6 +29,7 @@ import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dump.DumpHandler; import com.android.systemui.dump.DumpManager; import com.android.systemui.media.MediaDataManager; import com.android.systemui.plugins.ActivityStarter; @@ -181,8 +182,10 @@ public interface CentralSurfacesDependenciesModule { static CommandQueue provideCommandQueue( Context context, ProtoTracer protoTracer, - CommandRegistry registry) { - return new CommandQueue(context, protoTracer, registry); + CommandRegistry registry, + DumpHandler dumpHandler + ) { + return new CommandQueue(context, protoTracer, registry, dumpHandler); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt index d88f07ca304c..737b4812d4fb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt @@ -25,11 +25,12 @@ import android.view.Gravity import android.view.View import android.widget.FrameLayout import com.android.internal.annotations.GuardedBy -import com.android.systemui.animation.Interpolators import com.android.systemui.R +import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.shade.ShadeExpansionStateManager import com.android.systemui.statusbar.StatusBarState.SHADE import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener @@ -42,7 +43,6 @@ import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN import com.android.systemui.util.leak.RotationUtils.Rotation - import java.util.concurrent.Executor import javax.inject.Inject @@ -67,7 +67,8 @@ class PrivacyDotViewController @Inject constructor( private val stateController: StatusBarStateController, private val configurationController: ConfigurationController, private val contentInsetsProvider: StatusBarContentInsetsProvider, - private val animationScheduler: SystemStatusAnimationScheduler + private val animationScheduler: SystemStatusAnimationScheduler, + shadeExpansionStateManager: ShadeExpansionStateManager ) { private lateinit var tl: View private lateinit var tr: View @@ -128,6 +129,13 @@ class PrivacyDotViewController @Inject constructor( updateStatusBarState() } }) + + shadeExpansionStateManager.addQsExpansionListener { isQsExpanded -> + dlog("setQsExpanded $isQsExpanded") + synchronized(lock) { + nextViewState = nextViewState.copy(qsExpanded = isQsExpanded) + } + } } fun setUiExecutor(e: DelayableExecutor) { @@ -138,13 +146,6 @@ class PrivacyDotViewController @Inject constructor( showingListener = l } - fun setQsExpanded(expanded: Boolean) { - dlog("setQsExpanded $expanded") - synchronized(lock) { - nextViewState = nextViewState.copy(qsExpanded = expanded) - } - } - @UiThread fun setNewRotation(rot: Int) { dlog("updateRotation: $rot") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt index 36b8333688ae..2734511de78c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt @@ -28,12 +28,7 @@ class NotifPipelineFlags @Inject constructor( fun isDevLoggingEnabled(): Boolean = featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING) - fun isSmartspaceDedupingEnabled(): Boolean = - featureFlags.isEnabled(Flags.SMARTSPACE) && - featureFlags.isEnabled(Flags.SMARTSPACE_DEDUPING) - - fun removeUnrankedNotifs(): Boolean = - featureFlags.isEnabled(Flags.REMOVE_UNRANKED_NOTIFICATIONS) + fun isSmartspaceDedupingEnabled(): Boolean = featureFlags.isEnabled(Flags.SMARTSPACE) fun fullScreenIntentRequiresKeyguard(): Boolean = featureFlags.isEnabled(Flags.FSI_REQUIRES_KEYGUARD) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index 7242506f1015..d97b712df030 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -18,8 +18,10 @@ package com.android.systemui.statusbar.notification import android.animation.ObjectAnimator import android.util.FloatProperty +import com.android.systemui.Dumpable import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.ShadeExpansionChangeEvent import com.android.systemui.shade.ShadeExpansionListener @@ -32,17 +34,20 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener +import java.io.PrintWriter import javax.inject.Inject import kotlin.math.min @SysUISingleton class NotificationWakeUpCoordinator @Inject constructor( + dumpManager: DumpManager, private val mHeadsUpManager: HeadsUpManager, private val statusBarStateController: StatusBarStateController, private val bypassController: KeyguardBypassController, private val dozeParameters: DozeParameters, private val screenOffAnimationController: ScreenOffAnimationController -) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, ShadeExpansionListener { +) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, ShadeExpansionListener, + Dumpable { private val mNotificationVisibility = object : FloatProperty<NotificationWakeUpCoordinator>( "notificationVisibility") { @@ -60,6 +65,7 @@ class NotificationWakeUpCoordinator @Inject constructor( private var mLinearDozeAmount: Float = 0.0f private var mDozeAmount: Float = 0.0f + private var mDozeAmountSource: String = "init" private var mNotificationVisibleAmount = 0.0f private var mNotificationsVisible = false private var mNotificationsVisibleForExpansion = false @@ -142,6 +148,7 @@ class NotificationWakeUpCoordinator @Inject constructor( } init { + dumpManager.registerDumpable(this) mHeadsUpManager.addListener(this) statusBarStateController.addCallback(this) addListener(object : WakeUpListener { @@ -248,13 +255,14 @@ class NotificationWakeUpCoordinator @Inject constructor( // Let's notify the scroller that an animation started notifyAnimationStart(mLinearDozeAmount == 1.0f) } - setDozeAmount(linear, eased) + setDozeAmount(linear, eased, source = "StatusBar") } - fun setDozeAmount(linear: Float, eased: Float) { + fun setDozeAmount(linear: Float, eased: Float, source: String) { val changed = linear != mLinearDozeAmount mLinearDozeAmount = linear mDozeAmount = eased + mDozeAmountSource = source mStackScrollerController.setDozeAmount(mDozeAmount) updateHideAmount() if (changed && linear == 0.0f) { @@ -271,7 +279,7 @@ class NotificationWakeUpCoordinator @Inject constructor( // undefined state, so it's an indication that we should do state cleanup. We override // the doze amount to 0f (not dozing) so that the notifications are no longer hidden. // See: UnlockedScreenOffAnimationController.onFinishedWakingUp() - setDozeAmount(0f, 0f) + setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)") } if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) { @@ -311,12 +319,11 @@ class NotificationWakeUpCoordinator @Inject constructor( */ private fun overrideDozeAmountIfBypass(): Boolean { if (bypassController.bypassEnabled) { - var amount = 1.0f - if (statusBarStateController.state == StatusBarState.SHADE || - statusBarStateController.state == StatusBarState.SHADE_LOCKED) { - amount = 0.0f + if (statusBarStateController.state == StatusBarState.KEYGUARD) { + setDozeAmount(1f, 1f, source = "Override: bypass (keyguard)") + } else { + setDozeAmount(0f, 0f, source = "Override: bypass (shade)") } - setDozeAmount(amount, amount) return true } return false @@ -332,7 +339,7 @@ class NotificationWakeUpCoordinator @Inject constructor( */ private fun overrideDozeAmountIfAnimatingScreenOff(linearDozeAmount: Float): Boolean { if (screenOffAnimationController.overrideNotificationsFullyDozingOnKeyguard()) { - setDozeAmount(1f, 1f) + setDozeAmount(1f, 1f, source = "Override: animating screen off") return true } @@ -414,6 +421,26 @@ class NotificationWakeUpCoordinator @Inject constructor( private fun shouldAnimateVisibility() = dozeParameters.alwaysOn && !dozeParameters.displayNeedsBlanking + override fun dump(pw: PrintWriter, args: Array<out String>) { + pw.println("mLinearDozeAmount: $mLinearDozeAmount") + pw.println("mDozeAmount: $mDozeAmount") + pw.println("mDozeAmountSource: $mDozeAmountSource") + pw.println("mNotificationVisibleAmount: $mNotificationVisibleAmount") + pw.println("mNotificationsVisible: $mNotificationsVisible") + pw.println("mNotificationsVisibleForExpansion: $mNotificationsVisibleForExpansion") + pw.println("mVisibilityAmount: $mVisibilityAmount") + pw.println("mLinearVisibilityAmount: $mLinearVisibilityAmount") + pw.println("pulseExpanding: $pulseExpanding") + pw.println("state: ${StatusBarState.toString(state)}") + pw.println("fullyAwake: $fullyAwake") + pw.println("wakingUp: $wakingUp") + pw.println("willWakeUp: $willWakeUp") + pw.println("collapsedEnoughToHide: $collapsedEnoughToHide") + pw.println("pulsing: $pulsing") + pw.println("notificationsFullyHidden: $notificationsFullyHidden") + pw.println("canShowPulsingHuns: $canShowPulsingHuns") + } + interface WakeUpListener { /** * Called whenever the notifications are fully hidden or shown diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java index 2887f975d46c..df35c9e6832a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java @@ -602,7 +602,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable { mInconsistencyTracker.logNewMissingNotifications(rankingMap); mInconsistencyTracker.logNewInconsistentRankings(currentEntriesWithoutRankings, rankingMap); - if (currentEntriesWithoutRankings != null && mNotifPipelineFlags.removeUnrankedNotifs()) { + if (currentEntriesWithoutRankings != null) { for (NotificationEntry entry : currentEntriesWithoutRankings.values()) { entry.mCancellationReason = REASON_UNKNOWN; tryRemoveNotification(entry); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index 8f3eb4f7e223..8a31ed9271ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.app.Notification import android.app.Notification.GROUP_ALERT_SUMMARY import android.util.ArrayMap +import android.util.ArraySet +import com.android.internal.annotations.VisibleForTesting import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.NotificationRemoteInputManager import com.android.systemui.statusbar.notification.collection.GroupEntry @@ -70,6 +72,7 @@ class HeadsUpCoordinator @Inject constructor( @Main private val mExecutor: DelayableExecutor, ) : Coordinator { private val mEntriesBindingUntil = ArrayMap<String, Long>() + private val mEntriesUpdateTimes = ArrayMap<String, Long>() private var mEndLifetimeExtension: OnEndLifetimeExtensionCallback? = null private lateinit var mNotifPipeline: NotifPipeline private var mNow: Long = -1 @@ -264,6 +267,9 @@ class HeadsUpCoordinator @Inject constructor( } // After this method runs, all posted entries should have been handled (or skipped). mPostedEntries.clear() + + // Also take this opportunity to clean up any stale entry update times + cleanUpEntryUpdateTimes() } /** @@ -378,6 +384,9 @@ class HeadsUpCoordinator @Inject constructor( isAlerting = false, isBinding = false, ) + + // Record the last updated time for this key + setUpdateTime(entry, mSystemClock.currentTimeMillis()) } /** @@ -419,6 +428,9 @@ class HeadsUpCoordinator @Inject constructor( cancelHeadsUpBind(posted.entry) } } + + // Update last updated time for this entry + setUpdateTime(entry, mSystemClock.currentTimeMillis()) } /** @@ -426,6 +438,7 @@ class HeadsUpCoordinator @Inject constructor( */ override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { mPostedEntries.remove(entry.key) + mEntriesUpdateTimes.remove(entry.key) cancelHeadsUpBind(entry) val entryKey = entry.key if (mHeadsUpManager.isAlerting(entryKey)) { @@ -454,7 +467,12 @@ class HeadsUpCoordinator @Inject constructor( // never) in mPostedEntries to need to alert, we need to check every notification // known to the pipeline. for (entry in mNotifPipeline.allNotifs) { - // The only entries we can consider alerting for here are entries that have never + // Only consider entries that are recent enough, since we want to apply a fairly + // strict threshold for when an entry should be updated via only ranking and not an + // app-provided notification update. + if (!isNewEnoughForRankingUpdate(entry)) continue + + // The only entries we consider alerting for here are entries that have never // interrupted and that now say they should heads up; if they've alerted in the // past, we don't want to incorrectly alert a second time if there wasn't an // explicit notification update. @@ -486,6 +504,41 @@ class HeadsUpCoordinator @Inject constructor( (entry.sbn.notification.flags and Notification.FLAG_ONLY_ALERT_ONCE) == 0) } + /** + * Sets the updated time for the given entry to the specified time. + */ + @VisibleForTesting + fun setUpdateTime(entry: NotificationEntry, time: Long) { + mEntriesUpdateTimes[entry.key] = time + } + + /** + * Checks whether the entry is new enough to be updated via ranking update. + * We want to avoid updating an entry too long after it was originally posted/updated when we're + * only reacting to a ranking change, as relevant ranking updates are expected to come in + * fairly soon after the posting of a notification. + */ + private fun isNewEnoughForRankingUpdate(entry: NotificationEntry): Boolean { + // If we don't have an update time for this key, default to "too old" + if (!mEntriesUpdateTimes.containsKey(entry.key)) return false + + val updateTime = mEntriesUpdateTimes[entry.key] ?: return false + return (mSystemClock.currentTimeMillis() - updateTime) <= MAX_RANKING_UPDATE_DELAY_MS + } + + private fun cleanUpEntryUpdateTimes() { + // Because we won't update entries that are older than this amount of time anyway, clean + // up any entries that are too old to notify. + val toRemove = ArraySet<String>() + for ((key, updateTime) in mEntriesUpdateTimes) { + if (updateTime == null || + (mSystemClock.currentTimeMillis() - updateTime) > MAX_RANKING_UPDATE_DELAY_MS) { + toRemove.add(key) + } + } + mEntriesUpdateTimes.removeAll(toRemove) + } + /** When an action is pressed on a notification, end HeadsUp lifetime extension. */ private val mActionPressListener = Consumer<NotificationEntry> { entry -> if (mNotifsExtendingLifetime.contains(entry)) { @@ -597,6 +650,9 @@ class HeadsUpCoordinator @Inject constructor( companion object { private const val TAG = "HeadsUpCoordinator" private const val BIND_TIMEOUT = 1000L + + // This value is set to match MAX_SOUND_DELAY_MS in NotificationRecord. + private const val MAX_RANKING_UPDATE_DELAY_MS: Long = 2000 } data class PostedEntry( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java index 6e76691ae1b1..d2db6224ef52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java @@ -407,7 +407,10 @@ public class PreparationCoordinator implements Coordinator { mLogger.logGroupInflationTookTooLong(group); return false; } - if (mInflatingNotifs.contains(group.getSummary())) { + // Only delay release if the summary is not inflated. + // TODO(253454977): Once we ensure that all other pipeline filtering and pruning has been + // done by this point, we can revert back to checking for mInflatingNotifs.contains(...) + if (group.getSummary() != null && !isInflated(group.getSummary())) { mLogger.logDelayingGroupRelease(group, group.getSummary()); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt index b2cb23bd11aa..a5278c3d0ad3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt @@ -23,6 +23,7 @@ import com.android.systemui.statusbar.notification.NotificationActivityStarter import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl import com.android.systemui.statusbar.notification.collection.render.NotifStackController import com.android.systemui.statusbar.notification.stack.NotificationListContainer +import com.android.systemui.statusbar.phone.CentralSurfaces /** * The master controller for all notifications-related work @@ -32,6 +33,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationListContain */ interface NotificationsController { fun initialize( + centralSurfaces: CentralSurfaces, presenter: NotificationPresenter, listContainer: NotificationListContainer, stackController: NotifStackController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt index 8e646a37a4b3..83cf0c8e8aba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt @@ -56,7 +56,6 @@ import javax.inject.Inject */ @SysUISingleton class NotificationsControllerImpl @Inject constructor( - private val centralSurfaces: Lazy<CentralSurfaces>, private val notificationListener: NotificationListener, private val commonNotifCollection: Lazy<CommonNotifCollection>, private val notifPipeline: Lazy<NotifPipeline>, @@ -76,6 +75,7 @@ class NotificationsControllerImpl @Inject constructor( ) : NotificationsController { override fun initialize( + centralSurfaces: CentralSurfaces, presenter: NotificationPresenter, listContainer: NotificationListContainer, stackController: NotifStackController, @@ -92,8 +92,8 @@ class NotificationsControllerImpl @Inject constructor( notificationRowBinder.setNotificationClicker( clickerBuilder.build( - Optional.of( - centralSurfaces.get()), bubblesOptional, notificationActivityStarter)) + Optional.ofNullable(centralSurfaces), bubblesOptional, + notificationActivityStarter)) notificationRowBinder.setUpWithPresenter( presenter, listContainer, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt index 744166d87907..14856dafdb11 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt @@ -24,6 +24,7 @@ import com.android.systemui.statusbar.notification.NotificationActivityStarter import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl import com.android.systemui.statusbar.notification.collection.render.NotifStackController import com.android.systemui.statusbar.notification.stack.NotificationListContainer +import com.android.systemui.statusbar.phone.CentralSurfaces import javax.inject.Inject /** @@ -34,6 +35,7 @@ class NotificationsControllerStub @Inject constructor( ) : NotificationsController { override fun initialize( + centralSurfaces: CentralSurfaces, presenter: NotificationPresenter, listContainer: NotificationListContainer, stackController: NotifStackController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java index c5a69217a1ac..c4f5a3a30608 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java @@ -17,6 +17,8 @@ package com.android.systemui.statusbar.notification.interruption; import static com.android.systemui.statusbar.StatusBarState.SHADE; +import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD; +import static com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR; import android.app.NotificationManager; import android.content.ContentResolver; @@ -32,6 +34,8 @@ import android.service.notification.StatusBarNotification; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -68,10 +72,30 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter private final NotificationInterruptLogger mLogger; private final NotifPipelineFlags mFlags; private final KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider; + private final UiEventLogger mUiEventLogger; @VisibleForTesting protected boolean mUseHeadsUp = false; + public enum NotificationInterruptEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "FSI suppressed for suppressive GroupAlertBehavior") + FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(1235), + + @UiEvent(doc = "FSI suppressed for requiring neither HUN nor keyguard") + FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD(1236); + + private final int mId; + + NotificationInterruptEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } + @Inject public NotificationInterruptStateProviderImpl( ContentResolver contentResolver, @@ -85,7 +109,8 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter NotificationInterruptLogger logger, @Main Handler mainHandler, NotifPipelineFlags flags, - KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) { + KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider, + UiEventLogger uiEventLogger) { mContentResolver = contentResolver; mPowerManager = powerManager; mDreamManager = dreamManager; @@ -97,6 +122,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter mLogger = logger; mFlags = flags; mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider; + mUiEventLogger = uiEventLogger; ContentObserver headsUpObserver = new ContentObserver(mainHandler) { @Override public void onChange(boolean selfChange) { @@ -203,7 +229,9 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter // b/231322873: Detect and report an event when a notification has both an FSI and a // suppressive groupAlertBehavior, and now correctly block the FSI from firing. final int uid = entry.getSbn().getUid(); + final String packageName = entry.getSbn().getPackageName(); android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "groupAlertBehavior"); + mUiEventLogger.log(FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR, uid, packageName); mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN"); return false; } @@ -249,7 +277,9 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter // Detect the case determined by b/231322873 to launch FSI while device is in use, // as blocked by the correct implementation, and report the event. final int uid = entry.getSbn().getUid(); + final String packageName = entry.getSbn().getPackageName(); android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "no hun or keyguard"); + mUiEventLogger.log(FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD, uid, packageName); mLogger.logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard"); return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index fa7bfaeb6c4d..169c90780926 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -262,8 +262,6 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn @Override void startActivity(Intent intent, boolean dismissShade, Callback callback); - void setQsExpanded(boolean expanded); - boolean isWakeUpComingFromTouch(); boolean isFalsingThresholdNeeded(); @@ -455,6 +453,9 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn void collapseShade(); + /** Collapse the shade, but conditional on a flag specific to the trigger of a bugreport. */ + void collapseShadeForBugreport(); + int getWakefulnessState(); boolean isScreenFullyOff(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 604e1467f950..b9eb8f9120af 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -885,6 +885,11 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mBubblesOptional.get().setExpandListener(mBubbleExpandListener); } + // Do not restart System UI when the bugreport flag changes. + mFeatureFlags.addListener(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT, event -> { + event.requestNoRestart(); + }); + mStatusBarSignalPolicy.init(); mKeyguardIndicationController.init(); @@ -1421,6 +1426,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mStackScrollerController.setNotificationActivityStarter(mNotificationActivityStarter); mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); mNotificationsController.initialize( + this, mPresenter, mNotifListContainer, mStackScrollerController.getNotifStackController(), @@ -1790,18 +1796,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { } @Override - public void setQsExpanded(boolean expanded) { - mNotificationShadeWindowController.setQsExpanded(expanded); - mNotificationPanelViewController.setStatusAccessibilityImportance(expanded - ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS - : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); - mNotificationPanelViewController.updateSystemUiStateFlags(); - if (getNavigationBarView() != null) { - getNavigationBarView().onStatusBarPanelStateChanged(); - } - } - - @Override public boolean isWakeUpComingFromTouch() { return mWakeUpComingFromTouch; } @@ -3580,6 +3574,13 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { } } + @Override + public void collapseShadeForBugreport() { + if (!mFeatureFlags.isEnabled(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT)) { + collapseShade(); + } + } + @VisibleForTesting final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index b987f6815000..b965ac97cc1c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -26,6 +26,7 @@ import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.shade.ShadeExpansionStateManager import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm @@ -95,14 +96,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr var bouncerShowing: Boolean = false var altBouncerShowing: Boolean = false var launchingAffordance: Boolean = false - var qSExpanded = false - set(value) { - val changed = field != value - field = value - if (changed && !value) { - maybePerformPendingUnlock() - } - } + var qsExpanded = false @Inject constructor( @@ -111,6 +105,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr statusBarStateController: StatusBarStateController, lockscreenUserManager: NotificationLockscreenUserManager, keyguardStateController: KeyguardStateController, + shadeExpansionStateManager: ShadeExpansionStateManager, dumpManager: DumpManager ) { this.mKeyguardStateController = keyguardStateController @@ -132,6 +127,14 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr } }) + shadeExpansionStateManager.addQsExpansionListener { isQsExpanded -> + val changed = qsExpanded != isQsExpanded + qsExpanded = isQsExpanded + if (changed && !isQsExpanded) { + maybePerformPendingUnlock() + } + } + val dismissByDefault = if (context.resources.getBoolean( com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0 tunerService.addTunable(object : TunerService.Tunable { @@ -160,7 +163,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr ): Boolean { if (biometricSourceType == BiometricSourceType.FACE && bypassEnabled) { val can = canBypass() - if (!can && (isPulseExpanding || qSExpanded)) { + if (!can && (isPulseExpanding || qsExpanded)) { pendingUnlock = PendingUnlock(biometricSourceType, isStrongBiometric) } return can @@ -189,7 +192,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr altBouncerShowing -> true statusBarStateController.state != StatusBarState.KEYGUARD -> false launchingAffordance -> false - isPulseExpanding || qSExpanded -> false + isPulseExpanding || qsExpanded -> false else -> true } } @@ -214,7 +217,7 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr pw.println(" altBouncerShowing: $altBouncerShowing") pw.println(" isPulseExpanding: $isPulseExpanding") pw.println(" launchingAffordance: $launchingAffordance") - pw.println(" qSExpanded: $qSExpanded") + pw.println(" qSExpanded: $qsExpanded") pw.println(" hasFaceFeature: $hasFaceFeature") } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java index 00c3e8fac0b4..5e2a7c8ca540 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java @@ -26,6 +26,7 @@ import android.view.ViewGroup; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; +import com.android.systemui.animation.Expandable; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.plugins.ActivityStarter; @@ -67,7 +68,7 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> { ActivityLaunchAnimator.Controller.fromView(v, null), true /* showOverlockscreenwhenlocked */, UserHandle.SYSTEM); } else { - mUserSwitchDialogController.showDialog(v); + mUserSwitchDialogController.showDialog(v.getContext(), Expandable.fromView(v)); } } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index ece7ee0ec98a..86f6ff850409 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -372,7 +372,7 @@ public interface StatusBarIconController { mIconSize = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.status_bar_icon_size); - if (statusBarPipelineFlags.isNewPipelineFrontendEnabled()) { + if (statusBarPipelineFlags.useNewMobileIcons()) { // This starts the flow for the new pipeline, and will notify us of changes mMobileIconsViewModel = mobileUiAdapter.createMobileIconsViewModel(); MobileIconsBinder.bind(mGroup, mMobileIconsViewModel); @@ -451,7 +451,7 @@ public interface StatusBarIconController { @VisibleForTesting protected StatusIconDisplayable addWifiIcon(int index, String slot, WifiIconState state) { final BaseStatusBarFrameLayout view; - if (mStatusBarPipelineFlags.isNewPipelineFrontendEnabled()) { + if (mStatusBarPipelineFlags.useNewWifiIcon()) { view = onCreateModernStatusBarWifiView(slot); // When [ModernStatusBarWifiView] is created, it will automatically apply the // correct view state so we don't need to call applyWifiState. @@ -474,9 +474,9 @@ public interface StatusBarIconController { String slot, MobileIconState state ) { - if (mStatusBarPipelineFlags.isNewPipelineFrontendEnabled()) { + if (mStatusBarPipelineFlags.useNewMobileIcons()) { throw new IllegalStateException("Attempting to add a mobile icon while the new " - + "pipeline is enabled is not supported"); + + "icons are enabled is not supported"); } // Use the `subId` field as a key to query for the correct context @@ -497,7 +497,7 @@ public interface StatusBarIconController { String slot, int subId ) { - if (!mStatusBarPipelineFlags.isNewPipelineFrontendEnabled()) { + if (!mStatusBarPipelineFlags.useNewMobileIcons()) { throw new IllegalStateException("Attempting to add a mobile icon using the new" + "pipeline, but the enabled flag is false."); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java index e106b9e327ef..31e960ad7d69 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java @@ -224,9 +224,9 @@ public class StatusBarIconControllerImpl implements Tunable, */ @Override public void setMobileIcons(String slot, List<MobileIconState> iconStates) { - if (mStatusBarPipelineFlags.isNewPipelineFrontendEnabled()) { + if (mStatusBarPipelineFlags.useNewMobileIcons()) { Log.d(TAG, "ignoring old pipeline callbacks, because the new " - + "pipeline frontend is enabled"); + + "icons are enabled"); return; } Slot mobileSlot = mStatusBarIconList.getSlot(slot); @@ -249,9 +249,9 @@ public class StatusBarIconControllerImpl implements Tunable, @Override public void setNewMobileIconSubIds(List<Integer> subIds) { - if (!mStatusBarPipelineFlags.isNewPipelineFrontendEnabled()) { + if (!mStatusBarPipelineFlags.useNewMobileIcons()) { Log.d(TAG, "ignoring new pipeline callback, " - + "since the frontend is disabled"); + + "since the new icons are disabled"); return; } Slot mobileSlot = mStatusBarIconList.getSlot("mobile"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt index 0d52f46e571f..e498ae451400 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone.userswitcher import android.content.Intent import android.os.UserHandle import android.view.View +import com.android.systemui.animation.Expandable import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.plugins.ActivityStarter @@ -75,7 +76,7 @@ class StatusBarUserSwitcherControllerImpl @Inject constructor( null /* ActivityLaunchAnimator.Controller */, true /* showOverlockscreenwhenlocked */, UserHandle.SYSTEM) } else { - userSwitcherDialogController.showDialog(view) + userSwitcherDialogController.showDialog(view.context, Expandable.fromView(view)) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt index 9b8b6434827e..06cd12dd1a0d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/StatusBarPipelineFlags.kt @@ -24,29 +24,19 @@ import javax.inject.Inject /** All flagging methods related to the new status bar pipeline (see b/238425913). */ @SysUISingleton class StatusBarPipelineFlags @Inject constructor(private val featureFlags: FeatureFlags) { - /** - * Returns true if we should run the new pipeline backend. - * - * The new pipeline backend hooks up to all our external callbacks, logs those callback inputs, - * and logs the output state. - */ - fun isNewPipelineBackendEnabled(): Boolean = - featureFlags.isEnabled(Flags.NEW_STATUS_BAR_PIPELINE_BACKEND) + /** True if we should display the mobile icons using the new status bar data pipeline. */ + fun useNewMobileIcons(): Boolean = featureFlags.isEnabled(Flags.NEW_STATUS_BAR_MOBILE_ICONS) - /** - * Returns true if we should run the new pipeline frontend *and* backend. - * - * The new pipeline frontend will use the outputted state from the new backend and will make the - * correct changes to the UI. - */ - fun isNewPipelineFrontendEnabled(): Boolean = - isNewPipelineBackendEnabled() && - featureFlags.isEnabled(Flags.NEW_STATUS_BAR_PIPELINE_FRONTEND) + /** True if we should display the wifi icon using the new status bar data pipeline. */ + fun useNewWifiIcon(): Boolean = featureFlags.isEnabled(Flags.NEW_STATUS_BAR_WIFI_ICON) + + // TODO(b/238425913): Add flags to only run the mobile backend or wifi backend so we get the + // logging without getting the UI effects. /** - * Returns true if we should apply some coloring to icons that were rendered with the new + * Returns true if we should apply some coloring to the wifi icon that was rendered with the new * pipeline to help with debugging. */ - // For now, just always apply the debug coloring if we've enabled frontend rendering. - fun useNewPipelineDebugColoring(): Boolean = isNewPipelineFrontendEnabled() + // For now, just always apply the debug coloring if we've enabled the new icon. + fun useWifiDebugColoring(): Boolean = useNewWifiIcon() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt index 681cf7254ae7..93448c1dee0e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt @@ -39,7 +39,6 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange -import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiActivityModel import java.util.concurrent.Executor @@ -64,6 +63,9 @@ interface WifiRepository { /** Observable for the current wifi enabled status. */ val isWifiEnabled: StateFlow<Boolean> + /** Observable for the current wifi default status. */ + val isWifiDefault: StateFlow<Boolean> + /** Observable for the current wifi network. */ val wifiNetwork: StateFlow<WifiNetworkModel> @@ -103,7 +105,7 @@ class WifiRepositoryImpl @Inject constructor( merge(wifiNetworkChangeEvents, wifiStateChangeEvents) .mapLatest { wifiManager.isWifiEnabled } .distinctUntilChanged() - .logOutputChange(logger, "enabled") + .logInputChange(logger, "enabled") .stateIn( scope = scope, started = SharingStarted.WhileSubscribed(), @@ -111,6 +113,39 @@ class WifiRepositoryImpl @Inject constructor( ) } + override val isWifiDefault: StateFlow<Boolean> = conflatedCallbackFlow { + // Note: This callback doesn't do any logging because we already log every network change + // in the [wifiNetwork] callback. + val callback = object : ConnectivityManager.NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) { + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities + ) { + // This method will always be called immediately after the network becomes the + // default, in addition to any time the capabilities change while the network is + // the default. + // If this network contains valid wifi info, then wifi is the default network. + val wifiInfo = networkCapabilitiesToWifiInfo(networkCapabilities) + trySend(wifiInfo != null) + } + + override fun onLost(network: Network) { + // The system no longer has a default network, so wifi is definitely not default. + trySend(false) + } + } + + connectivityManager.registerDefaultNetworkCallback(callback) + awaitClose { connectivityManager.unregisterNetworkCallback(callback) } + } + .distinctUntilChanged() + .logInputChange(logger, "isWifiDefault") + .stateIn( + scope, + started = SharingStarted.WhileSubscribed(), + initialValue = false + ) + override val wifiNetwork: StateFlow<WifiNetworkModel> = conflatedCallbackFlow { var currentWifi: WifiNetworkModel = WIFI_NETWORK_DEFAULT diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt index 04b17ed2924a..3a3e611de96a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt @@ -59,6 +59,9 @@ class WifiInteractor @Inject constructor( /** Our current enabled status. */ val isEnabled: Flow<Boolean> = wifiRepository.isWifiEnabled + /** Our current default status. */ + val isDefault: Flow<Boolean> = wifiRepository.isWifiDefault + /** Our current wifi network. See [WifiNetworkModel]. */ val wifiNetwork: Flow<WifiNetworkModel> = wifiRepository.wifiNetwork diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt index e23f8c7e97e0..cc6a375c40f1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt @@ -48,7 +48,7 @@ abstract class LocationBasedWifiViewModel( /** The color that should be used to tint the icon. */ val tint: Flow<Int> = flowOf( - if (statusBarPipelineFlags.useNewPipelineDebugColoring()) { + if (statusBarPipelineFlags.useWifiDebugColoring()) { debugTint } else { DEFAULT_TINT diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt index ebbd77b72014..160c577042a4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt @@ -124,9 +124,10 @@ constructor( private val wifiIcon: StateFlow<Icon.Resource?> = combine( interactor.isEnabled, + interactor.isDefault, interactor.isForceHidden, interactor.wifiNetwork, - ) { isEnabled, isForceHidden, wifiNetwork -> + ) { isEnabled, isDefault, isForceHidden, wifiNetwork -> if (!isEnabled || isForceHidden || wifiNetwork is WifiNetworkModel.CarrierMerged) { return@combine null } @@ -135,6 +136,7 @@ constructor( val icon = Icon.Resource(iconResId, wifiNetwork.contentDescription()) return@combine when { + isDefault -> icon wifiConstants.alwaysShowIconIfEnabled -> icon !connectivityConstants.hasDataCapabilities -> icon wifiNetwork is WifiNetworkModel.Active && wifiNetwork.isValidated -> icon diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java index dc73d1f007c6..f63d65246d9b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java @@ -36,6 +36,7 @@ import com.android.keyguard.KeyguardVisibilityHelper; import com.android.keyguard.dagger.KeyguardUserSwitcherScope; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.systemui.R; +import com.android.systemui.animation.Expandable; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -190,7 +191,8 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> mUiEventLogger.log( LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP); - mUserSwitchDialogController.showDialog(mUserAvatarViewWithBackground); + mUserSwitchDialogController.showDialog(mUserAvatarViewWithBackground.getContext(), + Expandable.fromView(mUserAvatarViewWithBackground)); }); mUserAvatarView.setAccessibilityDelegate(new View.AccessibilityDelegate() { diff --git a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt index 7f1195b78c77..7da2d47c1226 100644 --- a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt @@ -17,7 +17,8 @@ package com.android.systemui.user import android.os.Bundle -import android.view.View +import android.view.WindowInsets.Type +import android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE import androidx.activity.ComponentActivity import androidx.lifecycle.ViewModelProvider import com.android.systemui.R @@ -38,10 +39,10 @@ constructor( override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.user_switcher_fullscreen) - window.decorView.systemUiVisibility = - (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) + window.decorView.getWindowInsetsController().apply { + setSystemBarsBehavior(BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) + hide(Type.systemBars()) + } val viewModel = ViewModelProvider(this, viewModelFactory.get())[UserSwitcherViewModel::class.java] UserSwitcherViewBinder.bind( diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt index d768b6dc195a..b16dc5403a57 100644 --- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt @@ -220,7 +220,12 @@ constructor( val result = withContext(backgroundDispatcher) { manager.aliveUsers } if (result != null) { - _userInfos.value = result.sortedBy { it.creationTime } + _userInfos.value = + result + // Users should be sorted by ascending creation time. + .sortedBy { it.creationTime } + // The guest user is always last, regardless of creation time. + .sortedBy { it.isGuest } } } } diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt index 0d5c64b83e6e..dda78aad54c6 100644 --- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt @@ -429,6 +429,7 @@ constructor( isGuestEphemeral = currentlySelectedUserInfo.isEphemeral, isKeyguardShowing = keyguardInteractor.isKeyguardShowing(), onExitGuestUser = this::exitGuestUser, + dialogShower = dialogShower, ) ) return @@ -443,6 +444,7 @@ constructor( isGuestEphemeral = currentlySelectedUserInfo.isEphemeral, isKeyguardShowing = keyguardInteractor.isKeyguardShowing(), onExitGuestUser = this::exitGuestUser, + dialogShower = dialogShower, ) ) return @@ -477,6 +479,7 @@ constructor( userHandle = currentUser.userHandle, isKeyguardShowing = keyguardInteractor.isKeyguardShowing(), showEphemeralMessage = currentUser.isGuest && currentUser.isEphemeral, + dialogShower = dialogShower, ) ) } diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/model/ShowDialogRequestModel.kt b/packages/SystemUI/src/com/android/systemui/user/domain/model/ShowDialogRequestModel.kt index 08d7c5a26a25..177356e6b573 100644 --- a/packages/SystemUI/src/com/android/systemui/user/domain/model/ShowDialogRequestModel.kt +++ b/packages/SystemUI/src/com/android/systemui/user/domain/model/ShowDialogRequestModel.kt @@ -18,14 +18,18 @@ package com.android.systemui.user.domain.model import android.os.UserHandle +import com.android.systemui.qs.user.UserSwitchDialogController /** Encapsulates a request to show a dialog. */ -sealed class ShowDialogRequestModel { +sealed class ShowDialogRequestModel( + open val dialogShower: UserSwitchDialogController.DialogShower? = null, +) { data class ShowAddUserDialog( val userHandle: UserHandle, val isKeyguardShowing: Boolean, val showEphemeralMessage: Boolean, - ) : ShowDialogRequestModel() + override val dialogShower: UserSwitchDialogController.DialogShower?, + ) : ShowDialogRequestModel(dialogShower) data class ShowUserCreationDialog( val isGuest: Boolean, @@ -37,5 +41,6 @@ sealed class ShowDialogRequestModel { val isGuestEphemeral: Boolean, val isKeyguardShowing: Boolean, val onExitGuestUser: (guestId: Int, targetId: Int, forceRemoveGuest: Boolean) -> Unit, - ) : ShowDialogRequestModel() + override val dialogShower: UserSwitchDialogController.DialogShower?, + ) : ShowDialogRequestModel(dialogShower) } diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt index f7e19c0ca810..e9217209530b 100644 --- a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt @@ -19,8 +19,10 @@ package com.android.systemui.user.ui.dialog import android.app.Dialog import android.content.Context +import com.android.internal.jank.InteractionJankMonitor import com.android.settingslib.users.UserCreatingDialog import com.android.systemui.CoreStartable +import com.android.systemui.animation.DialogCuj import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.broadcast.BroadcastSender import com.android.systemui.dagger.SysUISingleton @@ -71,37 +73,58 @@ constructor( } } - currentDialog = + val (dialog, dialogCuj) = when (request) { is ShowDialogRequestModel.ShowAddUserDialog -> - AddUserDialog( - context = context.get(), - userHandle = request.userHandle, - isKeyguardShowing = request.isKeyguardShowing, - showEphemeralMessage = request.showEphemeralMessage, - falsingManager = falsingManager.get(), - broadcastSender = broadcastSender.get(), - dialogLaunchAnimator = dialogLaunchAnimator.get(), + Pair( + AddUserDialog( + context = context.get(), + userHandle = request.userHandle, + isKeyguardShowing = request.isKeyguardShowing, + showEphemeralMessage = request.showEphemeralMessage, + falsingManager = falsingManager.get(), + broadcastSender = broadcastSender.get(), + dialogLaunchAnimator = dialogLaunchAnimator.get(), + ), + DialogCuj( + InteractionJankMonitor.CUJ_USER_DIALOG_OPEN, + INTERACTION_JANK_ADD_NEW_USER_TAG, + ), ) is ShowDialogRequestModel.ShowUserCreationDialog -> - UserCreatingDialog( - context.get(), - request.isGuest, + Pair( + UserCreatingDialog( + context.get(), + request.isGuest, + ), + null, ) is ShowDialogRequestModel.ShowExitGuestDialog -> - ExitGuestDialog( - context = context.get(), - guestUserId = request.guestUserId, - isGuestEphemeral = request.isGuestEphemeral, - targetUserId = request.targetUserId, - isKeyguardShowing = request.isKeyguardShowing, - falsingManager = falsingManager.get(), - dialogLaunchAnimator = dialogLaunchAnimator.get(), - onExitGuestUserListener = request.onExitGuestUser, + Pair( + ExitGuestDialog( + context = context.get(), + guestUserId = request.guestUserId, + isGuestEphemeral = request.isGuestEphemeral, + targetUserId = request.targetUserId, + isKeyguardShowing = request.isKeyguardShowing, + falsingManager = falsingManager.get(), + dialogLaunchAnimator = dialogLaunchAnimator.get(), + onExitGuestUserListener = request.onExitGuestUser, + ), + DialogCuj( + InteractionJankMonitor.CUJ_USER_DIALOG_OPEN, + INTERACTION_JANK_EXIT_GUEST_MODE_TAG, + ), ) } + currentDialog = dialog + + if (request.dialogShower != null && dialogCuj != null) { + request.dialogShower?.showDialog(dialog, dialogCuj) + } else { + dialog.show() + } - currentDialog?.show() interactor.get().onDialogShown() } } @@ -120,4 +143,9 @@ constructor( } } } + + companion object { + private const val INTERACTION_JANK_ADD_NEW_USER_TAG = "add_new_user" + private const val INTERACTION_JANK_EXIT_GUEST_MODE_TAG = "exit_guest_mode" + } } diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Condition.java b/packages/SystemUI/src/com/android/systemui/util/condition/Condition.java index ecb365f43e3f..2c317dd391c0 100644 --- a/packages/SystemUI/src/com/android/systemui/util/condition/Condition.java +++ b/packages/SystemUI/src/com/android/systemui/util/condition/Condition.java @@ -172,10 +172,14 @@ public abstract class Condition implements CallbackController<Condition.Callback return Boolean.TRUE.equals(mIsConditionMet); } - private boolean shouldLog() { + protected final boolean shouldLog() { return Log.isLoggable(mTag, Log.DEBUG); } + protected final String getTag() { + return mTag; + } + /** * Callback that receives updates about whether the condition has been fulfilled. */ diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java index 4824f6744c6e..cb430ba454f0 100644 --- a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java +++ b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java @@ -117,6 +117,7 @@ public class Monitor { final SubscriptionState state = new SubscriptionState(subscription); mExecutor.execute(() -> { + if (shouldLog()) Log.d(mTag, "adding subscription"); mSubscriptions.put(token, state); // Add and associate conditions. @@ -143,7 +144,7 @@ public class Monitor { */ public void removeSubscription(@NotNull Subscription.Token token) { mExecutor.execute(() -> { - if (shouldLog()) Log.d(mTag, "removing callback"); + if (shouldLog()) Log.d(mTag, "removing subscription"); if (!mSubscriptions.containsKey(token)) { Log.e(mTag, "subscription not present:" + token); return; diff --git a/packages/SystemUI/src/com/android/systemui/util/proto/component_name.proto b/packages/SystemUI/src/com/android/systemui/util/proto/component_name.proto new file mode 100644 index 000000000000..b7166d96d401 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/proto/component_name.proto @@ -0,0 +1,26 @@ +/* + * 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. + */ + +syntax = "proto3"; + +package com.android.systemui.util; + +option java_multiple_files = true; + +message ComponentNameProto { + string package_name = 1; + string class_name = 2; +} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java index bb03a47e025c..627d738a895f 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.when; import android.content.res.Resources; import android.database.ContentObserver; +import android.graphics.Rect; import android.net.Uri; import android.os.UserHandle; import android.provider.Settings; @@ -45,6 +46,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; +import com.android.systemui.plugins.ClockAnimations; import com.android.systemui.plugins.ClockController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.clocks.AnimatableClockView; @@ -262,6 +264,19 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase { verify(mView).switchToClock(KeyguardClockSwitch.SMALL, /* animate */ true); } + @Test + public void testGetClockAnimationsForwardsToClock() { + ClockController mockClockController = mock(ClockController.class); + ClockAnimations mockClockAnimations = mock(ClockAnimations.class); + when(mClockEventController.getClock()).thenReturn(mockClockController); + when(mockClockController.getAnimations()).thenReturn(mockClockAnimations); + + Rect r1 = new Rect(1, 2, 3, 4); + Rect r2 = new Rect(5, 6, 7, 8); + mController.getClockAnimations().onPositionUpdated(r1, r2, 0.2f); + verify(mockClockAnimations).onPositionUpdated(r1, r2, 0.2f); + } + private void verifyAttachment(VerificationMode times) { verify(mClockRegistry, times).registerClockChangeListener( any(ClockRegistry.ClockChangeListener.class)); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java index 4dcaa7cf8c09..c94c97c9b638 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java @@ -16,12 +16,16 @@ package com.android.keyguard; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.graphics.Rect; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.ClockAnimations; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -108,4 +112,16 @@ public class KeyguardStatusViewControllerTest extends SysuiTestCase { configurationListenerArgumentCaptor.getValue().onLocaleListChanged(); verify(mKeyguardClockSwitchController).onLocaleListChanged(); } + + @Test + public void getClockAnimations_forwardsToClockSwitch() { + ClockAnimations mockClockAnimations = mock(ClockAnimations.class); + when(mKeyguardClockSwitchController.getClockAnimations()).thenReturn(mockClockAnimations); + + Rect r1 = new Rect(1, 2, 3, 4); + Rect r2 = new Rect(5, 6, 7, 8); + mController.getClockAnimations().onPositionUpdated(r1, r2, 0.3f); + + verify(mockClockAnimations).onPositionUpdated(r1, r2, 0.3f); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt index baeabc577fb7..c85334db9499 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt @@ -26,6 +26,7 @@ import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_ import android.hardware.biometrics.BiometricOverlayConstants.ShowReason import android.hardware.fingerprint.FingerprintManager import android.hardware.fingerprint.IUdfpsOverlayControllerCallback +import android.provider.Settings import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.LayoutInflater @@ -124,14 +125,18 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { whenever(udfpsEnrollView.context).thenReturn(context) } - private fun withReason(@ShowReason reason: Int, block: () -> Unit) { + private fun withReason( + @ShowReason reason: Int, + isDebuggable: Boolean = false, + block: () -> Unit + ) { controllerOverlay = UdfpsControllerOverlay( context, fingerprintManager, inflater, windowManager, accessibilityManager, statusBarStateController, shadeExpansionStateManager, statusBarKeyguardViewManager, keyguardUpdateMonitor, dialogManager, dumpManager, transitionController, configurationController, systemClock, keyguardStateController, unlockedScreenOffAnimationController, udfpsDisplayMode, REQUEST_ID, reason, - controllerCallback, onTouch, activityLaunchAnimator + controllerCallback, onTouch, activityLaunchAnimator, isDebuggable ) block() } @@ -151,11 +156,29 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { } @Test + fun showUdfpsOverlay_locate_withEnrollmentUiRemoved() { + Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 1) + withReason(REASON_ENROLL_FIND_SENSOR, isDebuggable = true) { + showUdfpsOverlay(isEnrollUseCase = false) + } + Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 0) + } + + @Test fun showUdfpsOverlay_enroll() = withReason(REASON_ENROLL_ENROLLING) { showUdfpsOverlay(isEnrollUseCase = true) } @Test + fun showUdfpsOverlay_enroll_withEnrollmentUiRemoved() { + Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 1) + withReason(REASON_ENROLL_ENROLLING, isDebuggable = true) { + showUdfpsOverlay(isEnrollUseCase = false) + } + Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 0) + } + + @Test fun showUdfpsOverlay_other() = withReason(REASON_AUTH_OTHER) { showUdfpsOverlay() } private fun withRotation(@Rotation rotation: Int, block: () -> Unit) { @@ -372,21 +395,33 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { context.resources.getStringArray(R.array.udfps_accessibility_touch_hints) val rotation = Surface.ROTATION_0 // touch at 0 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 0.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[0]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, 0.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[0]) // touch at 90 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, -1.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[1]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, -1.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[1]) // touch at 180 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(-1.0f /* x */, 0.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[2]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + -1.0f /* x */, 0.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[2]) // touch at 270 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 1.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[3]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, 1.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[3]) } fun testTouchOutsideAreaNoRotation90Degrees() = withReason(REASON_ENROLL_ENROLLING) { @@ -394,21 +429,33 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { context.resources.getStringArray(R.array.udfps_accessibility_touch_hints) val rotation = Surface.ROTATION_90 // touch at 0 degrees -> 90 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 0.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[1]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, 0.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[1]) // touch at 90 degrees -> 180 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, -1.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[2]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, -1.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[2]) // touch at 180 degrees -> 270 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(-1.0f /* x */, 0.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[3]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + -1.0f /* x */, 0.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[3]) // touch at 270 degrees -> 0 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 1.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[0]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, 1.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[0]) } fun testTouchOutsideAreaNoRotation270Degrees() = withReason(REASON_ENROLL_ENROLLING) { @@ -416,21 +463,33 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { context.resources.getStringArray(R.array.udfps_accessibility_touch_hints) val rotation = Surface.ROTATION_270 // touch at 0 degrees -> 270 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 0.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[3]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, 0.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[3]) // touch at 90 degrees -> 0 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, -1.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[0]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, -1.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[0]) // touch at 180 degrees -> 90 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(-1.0f /* x */, 0.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[1]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + -1.0f /* x */, 0.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[1]) // touch at 270 degrees -> 180 degrees - assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 1.0f /* y */, - 0.0f /* sensorX */, 0.0f /* sensorY */, rotation)) - .isEqualTo(touchHints[2]) + assertThat( + controllerOverlay.onTouchOutsideOfSensorAreaImpl( + 0.0f /* x */, 1.0f /* y */, + 0.0f /* sensorX */, 0.0f /* sensorY */, rotation + ) + ).isEqualTo(touchHints[2]) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 8923ba817568..d610709cdcda 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -659,7 +659,7 @@ public class UdfpsControllerTest extends SysuiTestCase { mUdfpsController.onAodInterrupt(0, 0, 0f, 0f); when(mUdfpsView.isDisplayConfigured()).thenReturn(true); // WHEN it is cancelled - mUdfpsController.onCancelUdfps(); + mUdfpsController.cancelAodInterrupt(); // THEN the display is unconfigured verify(mUdfpsView).unconfigureDisplay(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java index 3e9cf1e51b63..fa9c41a3cbb6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java @@ -35,6 +35,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerFake; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shade.ShadeExpansionStateManager; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.policy.BatteryController; @@ -71,6 +72,8 @@ public class FalsingCollectorImplTest extends SysuiTestCase { @Mock private KeyguardStateController mKeyguardStateController; @Mock + private ShadeExpansionStateManager mShadeExpansionStateManager; + @Mock private BatteryController mBatteryController; private final DockManagerFake mDockManager = new DockManagerFake(); private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); @@ -85,7 +88,8 @@ public class FalsingCollectorImplTest extends SysuiTestCase { mFalsingCollector = new FalsingCollectorImpl(mFalsingDataProvider, mFalsingManager, mKeyguardUpdateMonitor, mHistoryTracker, mProximitySensor, - mStatusBarStateController, mKeyguardStateController, mBatteryController, + mStatusBarStateController, mKeyguardStateController, mShadeExpansionStateManager, + mBatteryController, mDockManager, mFakeExecutor, mFakeSystemClock); } @@ -137,9 +141,9 @@ public class FalsingCollectorImplTest extends SysuiTestCase { public void testUnregisterSensor_QS() { mFalsingCollector.onScreenTurningOn(); reset(mProximitySensor); - mFalsingCollector.setQsExpanded(true); + mFalsingCollector.onQsExpansionChanged(true); verify(mProximitySensor).unregister(any(ThresholdSensor.Listener.class)); - mFalsingCollector.setQsExpanded(false); + mFalsingCollector.onQsExpansionChanged(false); verify(mProximitySensor).register(any(ThresholdSensor.Listener.class)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 781dc1550048..6091d3a93f14 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -23,10 +23,10 @@ import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -88,6 +88,8 @@ public class DozeTriggersTest extends SysuiTestCase { @Mock private ProximityCheck mProximityCheck; @Mock + private DozeLog mDozeLog; + @Mock private AuthController mAuthController; @Mock private UiEventLogger mUiEventLogger; @@ -127,7 +129,7 @@ public class DozeTriggersTest extends SysuiTestCase { mTriggers = new DozeTriggers(mContext, mHost, config, dozeParameters, asyncSensorManager, wakeLock, mDockManager, mProximitySensor, - mProximityCheck, mock(DozeLog.class), mBroadcastDispatcher, new FakeSettings(), + mProximityCheck, mDozeLog, mBroadcastDispatcher, new FakeSettings(), mAuthController, mUiEventLogger, mSessionTracker, mKeyguardStateController, mDevicePostureController); mTriggers.setDozeMachine(mMachine); @@ -342,6 +344,16 @@ public class DozeTriggersTest extends SysuiTestCase { verify(mProximityCheck).destroy(); } + @Test + public void testIsExecutingTransition_dropPulse() { + when(mHost.isPulsePending()).thenReturn(false); + when(mMachine.isExecutingTransition()).thenReturn(true); + + mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_LONG_PRESS, 100, 100, null); + + verify(mDozeLog).tracePulseDropped(anyString(), eq(null)); + } + private void waitForSensorManager() { mExecutor.runAllReady(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt index 65b44a14d2ad..65ae90b8f7e8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt @@ -19,11 +19,17 @@ package com.android.systemui.dump import androidx.test.filters.SmallTest import com.android.systemui.CoreStartable import com.android.systemui.Dumpable +import com.android.systemui.ProtoDumpable import com.android.systemui.SysuiTestCase import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq import com.google.common.truth.Truth.assertThat +import java.io.FileDescriptor +import java.io.PrintWriter +import java.io.StringWriter +import javax.inject.Provider import org.junit.Before import org.junit.Test import org.mockito.Mock @@ -31,9 +37,6 @@ import org.mockito.Mockito.anyInt import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -import java.io.PrintWriter -import java.io.StringWriter -import javax.inject.Provider @SmallTest class DumpHandlerTest : SysuiTestCase() { @@ -47,6 +50,8 @@ class DumpHandlerTest : SysuiTestCase() { @Mock private lateinit var pw: PrintWriter + @Mock + private lateinit var fd: FileDescriptor @Mock private lateinit var dumpable1: Dumpable @@ -56,6 +61,11 @@ class DumpHandlerTest : SysuiTestCase() { private lateinit var dumpable3: Dumpable @Mock + private lateinit var protoDumpable1: ProtoDumpable + @Mock + private lateinit var protoDumpable2: ProtoDumpable + + @Mock private lateinit var buffer1: LogBuffer @Mock private lateinit var buffer2: LogBuffer @@ -88,7 +98,7 @@ class DumpHandlerTest : SysuiTestCase() { // WHEN some of them are dumped explicitly val args = arrayOf("dumpable1", "dumpable3", "buffer2") - dumpHandler.dump(pw, args) + dumpHandler.dump(fd, pw, args) // THEN only the requested ones have their dump() method called verify(dumpable1).dump(pw, args) @@ -107,7 +117,7 @@ class DumpHandlerTest : SysuiTestCase() { // WHEN that module is dumped val args = arrayOf("dumpable1") - dumpHandler.dump(pw, args) + dumpHandler.dump(fd, pw, args) // THEN its dump() method is called verify(dumpable1).dump(pw, args) @@ -124,7 +134,7 @@ class DumpHandlerTest : SysuiTestCase() { // WHEN a critical dump is requested val args = arrayOf("--dump-priority", "CRITICAL") - dumpHandler.dump(pw, args) + dumpHandler.dump(fd, pw, args) // THEN all modules are dumped (but no buffers) verify(dumpable1).dump(pw, args) @@ -145,7 +155,7 @@ class DumpHandlerTest : SysuiTestCase() { // WHEN a normal dump is requested val args = arrayOf("--dump-priority", "NORMAL") - dumpHandler.dump(pw, args) + dumpHandler.dump(fd, pw, args) // THEN all buffers are dumped (but no modules) verify(dumpable1, never()).dump( @@ -168,11 +178,35 @@ class DumpHandlerTest : SysuiTestCase() { val spw = PrintWriter(stringWriter) // When a config dump is requested - dumpHandler.dump(spw, arrayOf("config")) + dumpHandler.dump(fd, spw, arrayOf("config")) assertThat(stringWriter.toString()).contains(EmptyCoreStartable::class.java.simpleName) } + @Test + fun testDumpAllProtoDumpables() { + dumpManager.registerDumpable("protoDumpable1", protoDumpable1) + dumpManager.registerDumpable("protoDumpable2", protoDumpable2) + + val args = arrayOf(DumpHandler.PROTO) + dumpHandler.dump(fd, pw, args) + + verify(protoDumpable1).dumpProto(any(), eq(args)) + verify(protoDumpable2).dumpProto(any(), eq(args)) + } + + @Test + fun testDumpSingleProtoDumpable() { + dumpManager.registerDumpable("protoDumpable1", protoDumpable1) + dumpManager.registerDumpable("protoDumpable2", protoDumpable2) + + val args = arrayOf(DumpHandler.PROTO, "protoDumpable1") + dumpHandler.dump(fd, pw, args) + + verify(protoDumpable1).dumpProto(any(), eq(args)) + verify(protoDumpable2, never()).dumpProto(any(), any()) + } + private class EmptyCoreStartable : CoreStartable { override fun start() {} } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java index 1c686c66e31e..5e9c1aaad309 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java @@ -22,7 +22,6 @@ import static junit.framework.Assert.assertNotNull; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -52,6 +51,7 @@ import android.text.SpannableStringBuilder; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.FrameLayout; import android.widget.TextView; import com.android.systemui.R; @@ -97,6 +97,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { private static final int DEFAULT_ICON_ID = R.drawable.ic_info_outline; private ViewGroup mRootView; + private ViewGroup mSecurityFooterView; private TextView mFooterText; private TestableImageView mPrimaryFooterIcon; private QSSecurityFooter mFooter; @@ -121,21 +122,26 @@ public class QSSecurityFooterTest extends SysuiTestCase { Looper looper = mTestableLooper.getLooper(); Handler mainHandler = new Handler(looper); when(mUserTracker.getUserInfo()).thenReturn(mock(UserInfo.class)); - mRootView = (ViewGroup) new LayoutInflaterBuilder(mContext) + mSecurityFooterView = (ViewGroup) new LayoutInflaterBuilder(mContext) .replace("ImageView", TestableImageView.class) .build().inflate(R.layout.quick_settings_security_footer, null, false); mFooterUtils = new QSSecurityFooterUtils(getContext(), getContext().getSystemService(DevicePolicyManager.class), mUserTracker, mainHandler, mActivityStarter, mSecurityController, looper, mDialogLaunchAnimator); - mFooter = new QSSecurityFooter(mRootView, mainHandler, mSecurityController, looper, - mBroadcastDispatcher, mFooterUtils); - mFooterText = mRootView.findViewById(R.id.footer_text); - mPrimaryFooterIcon = mRootView.findViewById(R.id.primary_footer_icon); + mFooter = new QSSecurityFooter(mSecurityFooterView, mainHandler, mSecurityController, + looper, mBroadcastDispatcher, mFooterUtils); + mFooterText = mSecurityFooterView.findViewById(R.id.footer_text); + mPrimaryFooterIcon = mSecurityFooterView.findViewById(R.id.primary_footer_icon); when(mSecurityController.getDeviceOwnerComponentOnAnyUser()) .thenReturn(DEVICE_OWNER_COMPONENT); when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT)) .thenReturn(DEVICE_OWNER_TYPE_DEFAULT); + + // mSecurityFooterView must have a ViewGroup parent so that + // DialogLaunchAnimator.Controller.fromView() does not return null. + mRootView = new FrameLayout(mContext); + mRootView.addView(mSecurityFooterView); ViewUtils.attachView(mRootView); mFooter.init(); @@ -153,7 +159,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { mFooter.refreshState(); TestableLooper.get(this).processAllMessages(); - assertEquals(View.GONE, mRootView.getVisibility()); + assertEquals(View.GONE, mSecurityFooterView.getVisibility()); } @Test @@ -165,7 +171,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { TestableLooper.get(this).processAllMessages(); assertEquals(mContext.getString(R.string.quick_settings_disclosure_management), mFooterText.getText()); - assertEquals(View.VISIBLE, mRootView.getVisibility()); + assertEquals(View.VISIBLE, mSecurityFooterView.getVisibility()); assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility()); assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource()); } @@ -181,7 +187,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management, MANAGING_ORGANIZATION), mFooterText.getText()); - assertEquals(View.VISIBLE, mRootView.getVisibility()); + assertEquals(View.VISIBLE, mSecurityFooterView.getVisibility()); assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility()); assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource()); } @@ -200,7 +206,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { assertEquals(mContext.getString( R.string.quick_settings_financed_disclosure_named_management, MANAGING_ORGANIZATION), mFooterText.getText()); - assertEquals(View.VISIBLE, mRootView.getVisibility()); + assertEquals(View.VISIBLE, mSecurityFooterView.getVisibility()); assertEquals(View.VISIBLE, mPrimaryFooterIcon.getVisibility()); assertEquals(DEFAULT_ICON_ID, mPrimaryFooterIcon.getLastImageResource()); } @@ -217,7 +223,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { mFooter.refreshState(); TestableLooper.get(this).processAllMessages(); - assertEquals(View.GONE, mRootView.getVisibility()); + assertEquals(View.GONE, mSecurityFooterView.getVisibility()); } @Test @@ -227,8 +233,8 @@ public class QSSecurityFooterTest extends SysuiTestCase { mFooter.refreshState(); TestableLooper.get(this).processAllMessages(); - assertFalse(mRootView.isClickable()); - assertEquals(View.GONE, mRootView.findViewById(R.id.footer_icon).getVisibility()); + assertFalse(mSecurityFooterView.isClickable()); + assertEquals(View.GONE, mSecurityFooterView.findViewById(R.id.footer_icon).getVisibility()); } @Test @@ -241,8 +247,9 @@ public class QSSecurityFooterTest extends SysuiTestCase { mFooter.refreshState(); TestableLooper.get(this).processAllMessages(); - assertTrue(mRootView.isClickable()); - assertEquals(View.VISIBLE, mRootView.findViewById(R.id.footer_icon).getVisibility()); + assertTrue(mSecurityFooterView.isClickable()); + assertEquals(View.VISIBLE, + mSecurityFooterView.findViewById(R.id.footer_icon).getVisibility()); } @Test @@ -254,8 +261,8 @@ public class QSSecurityFooterTest extends SysuiTestCase { mFooter.refreshState(); TestableLooper.get(this).processAllMessages(); - assertFalse(mRootView.isClickable()); - assertEquals(View.GONE, mRootView.findViewById(R.id.footer_icon).getVisibility()); + assertFalse(mSecurityFooterView.isClickable()); + assertEquals(View.GONE, mSecurityFooterView.findViewById(R.id.footer_icon).getVisibility()); } @Test @@ -734,11 +741,11 @@ public class QSSecurityFooterTest extends SysuiTestCase { @Test public void testDialogUsesDialogLauncher() { when(mSecurityController.isDeviceManaged()).thenReturn(true); - mFooter.onClick(mRootView); + mFooter.onClick(mSecurityFooterView); mTestableLooper.processAllMessages(); - verify(mDialogLaunchAnimator).showFromView(any(), eq(mRootView), any()); + verify(mDialogLaunchAnimator).show(any(), any()); } @Test @@ -775,7 +782,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { ArgumentCaptor<AlertDialog> dialogCaptor = ArgumentCaptor.forClass(AlertDialog.class); mTestableLooper.processAllMessages(); - verify(mDialogLaunchAnimator).showFromView(dialogCaptor.capture(), any(), any()); + verify(mDialogLaunchAnimator).show(dialogCaptor.capture(), any()); AlertDialog dialog = dialogCaptor.getValue(); dialog.create(); @@ -817,8 +824,8 @@ public class QSSecurityFooterTest extends SysuiTestCase { verify(mBroadcastDispatcher).registerReceiverWithHandler(captor.capture(), any(), any(), any()); - // Pretend view is not visible temporarily - mRootView.onVisibilityAggregated(false); + // Pretend view is not attached anymore. + mRootView.removeView(mSecurityFooterView); captor.getValue().onReceive(mContext, new Intent(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG)); mTestableLooper.processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java index 3c58b6fc1354..c452872a527e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java @@ -52,6 +52,7 @@ import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.dump.DumpManager; +import com.android.systemui.dump.nano.SystemUIProtoDump; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.qs.QSTile; @@ -114,8 +115,6 @@ public class QSTileHostTest extends SysuiTestCase { @Mock private DumpManager mDumpManager; @Mock - private QSTile.State mMockState; - @Mock private CentralSurfaces mCentralSurfaces; @Mock private QSLogger mQSLogger; @@ -195,7 +194,6 @@ public class QSTileHostTest extends SysuiTestCase { } private void setUpTileFactory() { - when(mMockState.toString()).thenReturn(MOCK_STATE_STRING); // Only create this kind of tiles when(mDefaultFactory.createTile(anyString())).thenAnswer( invocation -> { @@ -209,7 +207,11 @@ public class QSTileHostTest extends SysuiTestCase { } else if ("na".equals(spec)) { return new NotAvailableTile(mQSTileHost); } else if (CUSTOM_TILE_SPEC.equals(spec)) { - return mCustomTile; + QSTile tile = mCustomTile; + QSTile.State s = mock(QSTile.State.class); + s.spec = spec; + when(mCustomTile.getState()).thenReturn(s); + return tile; } else if ("internet".equals(spec) || "wifi".equals(spec) || "cell".equals(spec)) { @@ -647,7 +649,7 @@ public class QSTileHostTest extends SysuiTestCase { @Test public void testSetTileRemoved_removedBySystem() { int user = mUserTracker.getUserId(); - saveSetting("spec1" + CUSTOM_TILE_SPEC); + saveSetting("spec1," + CUSTOM_TILE_SPEC); // This will be done by TileServiceManager mQSTileHost.setTileAdded(CUSTOM_TILE, user, true); @@ -658,6 +660,27 @@ public class QSTileHostTest extends SysuiTestCase { .getBoolean(CUSTOM_TILE.flattenToString(), false)); } + @Test + public void testProtoDump_noTiles() { + SystemUIProtoDump proto = new SystemUIProtoDump(); + mQSTileHost.dumpProto(proto, new String[0]); + + assertEquals(0, proto.tiles.length); + } + + @Test + public void testTilesInOrder() { + saveSetting("spec1," + CUSTOM_TILE_SPEC); + + SystemUIProtoDump proto = new SystemUIProtoDump(); + mQSTileHost.dumpProto(proto, new String[0]); + + assertEquals(2, proto.tiles.length); + assertEquals("spec1", proto.tiles[0].getSpec()); + assertEquals(CUSTOM_TILE.getPackageName(), proto.tiles[1].getComponentName().packageName); + assertEquals(CUSTOM_TILE.getClassName(), proto.tiles[1].getComponentName().className); + } + private SharedPreferences getSharedPreferenecesForUser(int user) { return mUserFileManager.getSharedPreferences(QSTileHost.TILES, 0, user); } @@ -707,12 +730,9 @@ public class QSTileHostTest extends SysuiTestCase { @Override public State newTileState() { - return mMockState; - } - - @Override - public State getState() { - return mMockState; + State s = mock(QSTile.State.class); + when(s.toString()).thenReturn(MOCK_STATE_STRING); + return s; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileStateToProtoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/TileStateToProtoTest.kt new file mode 100644 index 000000000000..629c663943db --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileStateToProtoTest.kt @@ -0,0 +1,104 @@ +package com.android.systemui.qs + +import android.content.ComponentName +import android.service.quicksettings.Tile +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.qs.external.CustomTile +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class TileStateToProtoTest : SysuiTestCase() { + + companion object { + private const val TEST_LABEL = "label" + private const val TEST_SUBTITLE = "subtitle" + private const val TEST_SPEC = "spec" + private val TEST_COMPONENT = ComponentName("test_pkg", "test_cls") + } + + @Test + fun platformTile_INACTIVE() { + val state = + QSTile.State().apply { + spec = TEST_SPEC + label = TEST_LABEL + secondaryLabel = TEST_SUBTITLE + state = Tile.STATE_INACTIVE + } + val proto = state.toProto() + + assertThat(proto).isNotNull() + assertThat(proto?.hasSpec()).isTrue() + assertThat(proto?.spec).isEqualTo(TEST_SPEC) + assertThat(proto?.hasComponentName()).isFalse() + assertThat(proto?.label).isEqualTo(TEST_LABEL) + assertThat(proto?.secondaryLabel).isEqualTo(TEST_SUBTITLE) + assertThat(proto?.state).isEqualTo(Tile.STATE_INACTIVE) + assertThat(proto?.hasBooleanState()).isFalse() + } + + @Test + fun componentTile_UNAVAILABLE() { + val state = + QSTile.State().apply { + spec = CustomTile.toSpec(TEST_COMPONENT) + label = TEST_LABEL + secondaryLabel = TEST_SUBTITLE + state = Tile.STATE_UNAVAILABLE + } + val proto = state.toProto() + + assertThat(proto).isNotNull() + assertThat(proto?.hasSpec()).isFalse() + assertThat(proto?.hasComponentName()).isTrue() + val componentName = proto?.componentName + assertThat(componentName?.packageName).isEqualTo(TEST_COMPONENT.packageName) + assertThat(componentName?.className).isEqualTo(TEST_COMPONENT.className) + assertThat(proto?.label).isEqualTo(TEST_LABEL) + assertThat(proto?.secondaryLabel).isEqualTo(TEST_SUBTITLE) + assertThat(proto?.state).isEqualTo(Tile.STATE_UNAVAILABLE) + assertThat(proto?.hasBooleanState()).isFalse() + } + + @Test + fun booleanState_ACTIVE() { + val state = + QSTile.BooleanState().apply { + spec = TEST_SPEC + label = TEST_LABEL + secondaryLabel = TEST_SUBTITLE + state = Tile.STATE_ACTIVE + value = true + } + val proto = state.toProto() + + assertThat(proto).isNotNull() + assertThat(proto?.hasSpec()).isTrue() + assertThat(proto?.spec).isEqualTo(TEST_SPEC) + assertThat(proto?.hasComponentName()).isFalse() + assertThat(proto?.label).isEqualTo(TEST_LABEL) + assertThat(proto?.secondaryLabel).isEqualTo(TEST_SUBTITLE) + assertThat(proto?.state).isEqualTo(Tile.STATE_ACTIVE) + assertThat(proto?.hasBooleanState()).isTrue() + assertThat(proto?.booleanState).isTrue() + } + + @Test + fun noSpec_returnsNull() { + val state = + QSTile.State().apply { + label = TEST_LABEL + secondaryLabel = TEST_SUBTITLE + state = Tile.STATE_ACTIVE + } + val proto = state.toProto() + + assertThat(proto).isNull() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt index 3c258077c29d..2c2ddbb9b8c5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt @@ -23,13 +23,13 @@ import android.os.UserHandle import android.provider.Settings import android.testing.AndroidTestingRunner import android.testing.TestableLooper -import android.view.View import androidx.test.filters.SmallTest import com.android.internal.logging.nano.MetricsProto import com.android.internal.logging.testing.FakeMetricsLogger import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityLaunchAnimator +import com.android.systemui.animation.Expandable import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.globalactions.GlobalActionsDialogLite @@ -70,13 +70,13 @@ class FooterActionsInteractorTest : SysuiTestCase() { val underTest = utils.footerActionsInteractor(qsSecurityFooterUtils = qsSecurityFooterUtils) val quickSettingsContext = mock<Context>() - underTest.showDeviceMonitoringDialog(quickSettingsContext) - verify(qsSecurityFooterUtils).showDeviceMonitoringDialog(quickSettingsContext, null) - val view = mock<View>() - whenever(view.context).thenReturn(quickSettingsContext) - underTest.showDeviceMonitoringDialog(view) + underTest.showDeviceMonitoringDialog(quickSettingsContext, null) verify(qsSecurityFooterUtils).showDeviceMonitoringDialog(quickSettingsContext, null) + + val expandable = mock<Expandable>() + underTest.showDeviceMonitoringDialog(quickSettingsContext, expandable) + verify(qsSecurityFooterUtils).showDeviceMonitoringDialog(quickSettingsContext, expandable) } @Test @@ -85,8 +85,8 @@ class FooterActionsInteractorTest : SysuiTestCase() { val underTest = utils.footerActionsInteractor(uiEventLogger = uiEventLogger) val globalActionsDialogLite = mock<GlobalActionsDialogLite>() - val view = mock<View>() - underTest.showPowerMenuDialog(globalActionsDialogLite, view) + val expandable = mock<Expandable>() + underTest.showPowerMenuDialog(globalActionsDialogLite, expandable) // Event is logged. val logs = uiEventLogger.logs @@ -99,7 +99,7 @@ class FooterActionsInteractorTest : SysuiTestCase() { .showOrHideDialog( /* keyguardShowing= */ false, /* isDeviceProvisioned= */ true, - view, + expandable, ) } @@ -167,11 +167,11 @@ class FooterActionsInteractorTest : SysuiTestCase() { userSwitchDialogController = userSwitchDialogController, ) - val view = mock<View>() - underTest.showUserSwitcher(view) + val expandable = mock<Expandable>() + underTest.showUserSwitcher(context, expandable) // Dialog is shown. - verify(userSwitchDialogController).showDialog(view) + verify(userSwitchDialogController).showDialog(context, expandable) } @Test @@ -184,12 +184,9 @@ class FooterActionsInteractorTest : SysuiTestCase() { activityStarter = activityStarter, ) - // The clicked view. The context is necessary because it's used to build the intent, that - // we check below. - val view = mock<View>() - whenever(view.context).thenReturn(context) - - underTest.showUserSwitcher(view) + // The clicked expandable. + val expandable = mock<Expandable>() + underTest.showUserSwitcher(context, expandable) // Dialog is shown. val intentCaptor = argumentCaptor<Intent>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt index 9d908fdfb976..0a34810f4d3f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt @@ -20,12 +20,12 @@ import android.content.DialogInterface import android.content.Intent import android.provider.Settings import android.testing.AndroidTestingRunner -import android.view.View import android.widget.Button import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.animation.DialogLaunchAnimator +import com.android.systemui.animation.Expandable import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.PseudoGridView @@ -35,6 +35,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.mock import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -63,7 +64,7 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { @Mock private lateinit var userDetailViewAdapter: UserDetailView.Adapter @Mock - private lateinit var launchView: View + private lateinit var launchExpandable: Expandable @Mock private lateinit var neutralButton: Button @Mock @@ -79,7 +80,6 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - `when`(launchView.context).thenReturn(mContext) `when`(dialog.context).thenReturn(mContext) controller = UserSwitchDialogController( @@ -94,32 +94,34 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { @Test fun showDialog_callsDialogShow() { - controller.showDialog(launchView) - verify(dialogLaunchAnimator).showFromView(eq(dialog), eq(launchView), any(), anyBoolean()) + val launchController = mock<DialogLaunchAnimator.Controller>() + `when`(launchExpandable.dialogLaunchController(any())).thenReturn(launchController) + controller.showDialog(context, launchExpandable) + verify(dialogLaunchAnimator).show(eq(dialog), eq(launchController), anyBoolean()) verify(uiEventLogger).log(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN) } @Test fun dialog_showForAllUsers() { - controller.showDialog(launchView) + controller.showDialog(context, launchExpandable) verify(dialog).setShowForAllUsers(true) } @Test fun dialog_cancelOnTouchOutside() { - controller.showDialog(launchView) + controller.showDialog(context, launchExpandable) verify(dialog).setCanceledOnTouchOutside(true) } @Test fun adapterAndGridLinked() { - controller.showDialog(launchView) + controller.showDialog(context, launchExpandable) verify(userDetailViewAdapter).linkToViewGroup(any<PseudoGridView>()) } @Test fun doneButtonLogsCorrectly() { - controller.showDialog(launchView) + controller.showDialog(context, launchExpandable) verify(dialog).setPositiveButton(anyInt(), capture(clickCaptor)) @@ -132,7 +134,7 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { fun clickSettingsButton_noFalsing_opensSettings() { `when`(falsingManager.isFalseTap(anyInt())).thenReturn(false) - controller.showDialog(launchView) + controller.showDialog(context, launchExpandable) verify(dialog) .setNeutralButton(anyInt(), capture(clickCaptor), eq(false) /* dismissOnClick */) @@ -153,7 +155,7 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { fun clickSettingsButton_Falsing_notOpensSettings() { `when`(falsingManager.isFalseTap(anyInt())).thenReturn(true) - controller.showDialog(launchView) + controller.showDialog(context, launchExpandable) verify(dialog) .setNeutralButton(anyInt(), capture(clickCaptor), eq(false) /* dismissOnClick */) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java index d095add1c660..5c7e4e9691e6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java @@ -108,6 +108,7 @@ import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.media.MediaDataManager; import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.model.SysUiState; +import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QS; @@ -254,6 +255,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { @Mock private KeyguardMediaController mKeyguardMediaController; @Mock private PrivacyDotViewController mPrivacyDotViewController; @Mock private NavigationModeController mNavigationModeController; + @Mock private NavigationBarController mNavigationBarController; @Mock private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController; @Mock private ContentResolver mContentResolver; @Mock private TapAgainViewController mTapAgainViewController; @@ -377,6 +379,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { NotificationWakeUpCoordinator coordinator = new NotificationWakeUpCoordinator( + mDumpManager, mock(HeadsUpManagerPhone.class), new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager, mInteractionJankMonitor), @@ -392,6 +395,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mConfigurationController, mStatusBarStateController, mFalsingManager, + mShadeExpansionStateManager, mLockscreenShadeTransitionController, new FalsingCollectorFake(), mDumpManager); @@ -430,6 +434,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mView.getParent()).thenReturn(mViewParent); when(mQs.getHeader()).thenReturn(mQsHeader); when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN); + when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState); mMainHandler = new Handler(Looper.getMainLooper()); NotificationPanelViewController.PanelEventsEmitter panelEventsEmitter = @@ -473,6 +478,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mPrivacyDotViewController, mTapAgainViewController, mNavigationModeController, + mNavigationBarController, mFragmentService, mContentResolver, mRecordingController, @@ -757,6 +763,38 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { } @Test + public void testOnTouchEvent_expansionResumesAfterBriefTouch() { + // Start shade collapse with swipe up + onTouchEvent(MotionEvent.obtain(0L /* downTime */, + 0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */, + 0 /* metaState */)); + onTouchEvent(MotionEvent.obtain(0L /* downTime */, + 0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 300f /* y */, + 0 /* metaState */)); + onTouchEvent(MotionEvent.obtain(0L /* downTime */, + 0L /* eventTime */, MotionEvent.ACTION_UP, 0f /* x */, 300f /* y */, + 0 /* metaState */)); + + assertThat(mNotificationPanelViewController.getClosing()).isTrue(); + assertThat(mNotificationPanelViewController.getIsFlinging()).isTrue(); + + // simulate touch that does not exceed touch slop + onTouchEvent(MotionEvent.obtain(2L /* downTime */, + 2L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 300f /* y */, + 0 /* metaState */)); + + mNotificationPanelViewController.setTouchSlopExceeded(false); + + onTouchEvent(MotionEvent.obtain(2L /* downTime */, + 2L /* eventTime */, MotionEvent.ACTION_UP, 0f /* x */, 300f /* y */, + 0 /* metaState */)); + + // fling should still be called after a touch that does not exceed touch slop + assertThat(mNotificationPanelViewController.getClosing()).isTrue(); + assertThat(mNotificationPanelViewController.getIsFlinging()).isTrue(); + } + + @Test public void handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() { when(mCommandQueue.panelsEnabled()).thenReturn(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt index 12ef036d89d0..bdafc7df33bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt @@ -66,6 +66,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Mock private lateinit var largeScreenShadeHeaderController: LargeScreenShadeHeaderController @Mock + private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager + @Mock private lateinit var featureFlags: FeatureFlags @Captor lateinit var navigationModeCaptor: ArgumentCaptor<ModeChangedListener> @@ -96,6 +98,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { navigationModeController, overviewProxyService, largeScreenShadeHeaderController, + shadeExpansionStateManager, featureFlags, delayableExecutor ) @@ -380,6 +383,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { navigationModeController, overviewProxyService, largeScreenShadeHeaderController, + shadeExpansionStateManager, featureFlags, delayableExecutor ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java index ad3d3d2958cb..95cf9d60b511 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java @@ -88,6 +88,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { @Mock private KeyguardStateController mKeyguardStateController; @Mock private ScreenOffAnimationController mScreenOffAnimationController; @Mock private AuthController mAuthController; + @Mock private ShadeExpansionStateManager mShadeExpansionStateManager; @Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters; private NotificationShadeWindowControllerImpl mNotificationShadeWindowController; @@ -103,7 +104,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, mColorExtractor, mDumpManager, mKeyguardStateController, - mScreenOffAnimationController, mAuthController) { + mScreenOffAnimationController, mAuthController, mShadeExpansionStateManager) { @Override protected boolean isDebuggable() { return false; diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt index eb34561d15a0..cc45cf88fa18 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/AnimatableClockViewTest.kt @@ -22,6 +22,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.TextAnimator +import com.android.systemui.util.mockito.any import org.junit.Before import org.junit.Rule import org.junit.Test @@ -55,7 +56,7 @@ class AnimatableClockViewTest : SysuiTestCase() { clockView.animateAppearOnLockscreen() clockView.measure(50, 50) - verify(mockTextAnimator).glyphFilter = null + verify(mockTextAnimator).glyphFilter = any() verify(mockTextAnimator).setTextStyle(300, -1.0f, 200, false, 350L, null, 0L, null) verifyNoMoreInteractions(mockTextAnimator) } @@ -66,7 +67,7 @@ class AnimatableClockViewTest : SysuiTestCase() { clockView.measure(50, 50) clockView.animateAppearOnLockscreen() - verify(mockTextAnimator, times(2)).glyphFilter = null + verify(mockTextAnimator, times(2)).glyphFilter = any() verify(mockTextAnimator).setTextStyle(100, -1.0f, 200, false, 0L, null, 0L, null) verify(mockTextAnimator).setTextStyle(300, -1.0f, 200, true, 350L, null, 0L, null) verifyNoMoreInteractions(mockTextAnimator) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt index 44cbe51a30ac..fbb8ebfb3e3b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/PulseExpansionHandlerTest.kt @@ -25,6 +25,7 @@ import com.android.systemui.classifier.FalsingCollector import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.shade.ShadeExpansionStateManager import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator import com.android.systemui.statusbar.notification.row.ExpandableView import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager @@ -56,6 +57,7 @@ class PulseExpansionHandlerTest : SysuiTestCase() { private val configurationController: ConfigurationController = mock() private val statusBarStateController: StatusBarStateController = mock() private val falsingManager: FalsingManager = mock() + private val shadeExpansionStateManager: ShadeExpansionStateManager = mock() private val lockscreenShadeTransitionController: LockscreenShadeTransitionController = mock() private val falsingCollector: FalsingCollector = mock() private val dumpManager: DumpManager = mock() @@ -65,7 +67,8 @@ class PulseExpansionHandlerTest : SysuiTestCase() { fun setUp() { whenever(expandableView.collapsedHeight).thenReturn(collapsedHeight) - pulseExpansionHandler = PulseExpansionHandler( + pulseExpansionHandler = + PulseExpansionHandler( mContext, wakeUpCoordinator, bypassController, @@ -74,10 +77,11 @@ class PulseExpansionHandlerTest : SysuiTestCase() { configurationController, statusBarStateController, falsingManager, + shadeExpansionStateManager, lockscreenShadeTransitionController, falsingCollector, dumpManager - ) + ) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java index 4b458f5a9123..dda7fadde2d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java @@ -31,8 +31,8 @@ public class GroupEntryBuilder { private long mCreationTime = 0; @Nullable private GroupEntry mParent = GroupEntry.ROOT_ENTRY; private NotifSection mNotifSection; - private NotificationEntry mSummary = null; - private List<NotificationEntry> mChildren = new ArrayList<>(); + @Nullable private NotificationEntry mSummary = null; + private final List<NotificationEntry> mChildren = new ArrayList<>(); /** Builds a new instance of GroupEntry */ public GroupEntry build() { @@ -41,7 +41,9 @@ public class GroupEntryBuilder { ge.getAttachState().setSection(mNotifSection); ge.setSummary(mSummary); - mSummary.setParent(ge); + if (mSummary != null) { + mSummary.setParent(ge); + } for (NotificationEntry child : mChildren) { ge.addChild(child); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java index 851517e1e35b..3b05321e1a6b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java @@ -1498,45 +1498,8 @@ public class NotifCollectionTest extends SysuiTestCase { } @Test - public void testMissingRankingWhenRemovalFeatureIsDisabled() { + public void testMissingRanking() { // GIVEN a pipeline with one two notifications - when(mNotifPipelineFlags.removeUnrankedNotifs()).thenReturn(false); - String key1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 1, "myTag")).key; - String key2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 2, "myTag")).key; - NotificationEntry entry1 = mCollectionListener.getEntry(key1); - NotificationEntry entry2 = mCollectionListener.getEntry(key2); - clearInvocations(mCollectionListener); - - // GIVEN the message for removing key1 gets does not reach NotifCollection - Ranking ranking1 = mNoMan.removeRankingWithoutEvent(key1); - // WHEN the message for removing key2 arrives - mNoMan.retractNotif(entry2.getSbn(), REASON_APP_CANCEL); - - // THEN only entry2 gets removed - verify(mCollectionListener).onEntryRemoved(eq(entry2), eq(REASON_APP_CANCEL)); - verify(mCollectionListener).onEntryCleanUp(eq(entry2)); - verify(mCollectionListener).onRankingApplied(); - verifyNoMoreInteractions(mCollectionListener); - verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any()); - verify(mLogger, never()).logRecoveredRankings(any(), anyInt()); - clearInvocations(mCollectionListener, mLogger); - - // WHEN a ranking update includes key1 again - mNoMan.setRanking(key1, ranking1); - mNoMan.issueRankingUpdate(); - - // VERIFY that we do nothing but log the 'recovery' - verify(mCollectionListener).onRankingUpdate(any()); - verify(mCollectionListener).onRankingApplied(); - verifyNoMoreInteractions(mCollectionListener); - verify(mLogger, never()).logMissingRankings(any(), anyInt(), any()); - verify(mLogger).logRecoveredRankings(eq(List.of(key1)), eq(0)); - } - - @Test - public void testMissingRankingWhenRemovalFeatureIsEnabled() { - // GIVEN a pipeline with one two notifications - when(mNotifPipelineFlags.removeUnrankedNotifs()).thenReturn(true); String key1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 1, "myTag")).key; String key2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 2, "myTag")).key; NotificationEntry entry1 = mCollectionListener.getEntry(key1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt index 340bc96f80c2..3ff7639e9262 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt @@ -674,7 +674,9 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { @Test fun testOnRankingApplied_newEntryShouldAlert() { // GIVEN that mEntry has never interrupted in the past, and now should + // and is new enough to do so assertFalse(mEntry.hasInterrupted()) + mCoordinator.setUpdateTime(mEntry, mSystemClock.currentTimeMillis()) setShouldHeadsUp(mEntry) whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry)) @@ -690,8 +692,9 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { @Test fun testOnRankingApplied_alreadyAlertedEntryShouldNotAlertAgain() { - // GIVEN that mEntry has alerted in the past + // GIVEN that mEntry has alerted in the past, even if it's new mEntry.setInterruption() + mCoordinator.setUpdateTime(mEntry, mSystemClock.currentTimeMillis()) setShouldHeadsUp(mEntry) whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry)) @@ -725,6 +728,27 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { verify(mHeadsUpManager).showNotification(mEntry) } + @Test + fun testOnRankingApplied_entryUpdatedButTooOld() { + // GIVEN that mEntry is added in a state where it should not HUN + setShouldHeadsUp(mEntry, false) + mCollectionListener.onEntryAdded(mEntry) + + // and it was actually added 10s ago + mCoordinator.setUpdateTime(mEntry, mSystemClock.currentTimeMillis() - 10000) + + // WHEN it is updated to HUN and then a ranking update occurs + setShouldHeadsUp(mEntry) + whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry)) + mCollectionListener.onRankingApplied() + mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry)) + mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry)) + + // THEN the notification is never bound or shown + verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any()) + verify(mHeadsUpManager, never()).showNotification(any()) + } + private fun setShouldHeadsUp(entry: NotificationEntry, should: Boolean = true) { whenever(mNotificationInterruptStateProvider.shouldHeadsUp(entry)).thenReturn(should) whenever(mNotificationInterruptStateProvider.checkHeadsUp(eq(entry), any())) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java index f4adf6927e31..b6b0b7738997 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java @@ -181,7 +181,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Test public void testInflatesNewNotification() { // WHEN there is a new notification - mCollectionListener.onEntryAdded(mEntry); + mCollectionListener.onEntryInit(mEntry); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); // THEN we inflate it @@ -194,7 +194,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Test public void testRebindsInflatedNotificationsOnUpdate() { // GIVEN an inflated notification - mCollectionListener.onEntryAdded(mEntry); + mCollectionListener.onEntryInit(mEntry); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); verify(mNotifInflater).inflateViews(eq(mEntry), any(), any()); mNotifInflater.invokeInflateCallbackForEntry(mEntry); @@ -213,7 +213,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Test public void testEntrySmartReplyAdditionWillRebindViews() { // GIVEN an inflated notification - mCollectionListener.onEntryAdded(mEntry); + mCollectionListener.onEntryInit(mEntry); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); verify(mNotifInflater).inflateViews(eq(mEntry), any(), any()); mNotifInflater.invokeInflateCallbackForEntry(mEntry); @@ -232,7 +232,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Test public void testEntryChangedToMinimizedSectionWillRebindViews() { // GIVEN an inflated notification - mCollectionListener.onEntryAdded(mEntry); + mCollectionListener.onEntryInit(mEntry); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); verify(mNotifInflater).inflateViews(eq(mEntry), mParamsCaptor.capture(), any()); assertFalse(mParamsCaptor.getValue().isLowPriority()); @@ -254,7 +254,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { public void testMinimizedEntryMovedIntoGroupWillRebindViews() { // GIVEN an inflated, minimized notification setSectionIsLowPriority(true); - mCollectionListener.onEntryAdded(mEntry); + mCollectionListener.onEntryInit(mEntry); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); verify(mNotifInflater).inflateViews(eq(mEntry), mParamsCaptor.capture(), any()); assertTrue(mParamsCaptor.getValue().isLowPriority()); @@ -275,7 +275,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Test public void testEntryRankChangeWillNotRebindViews() { // GIVEN an inflated notification - mCollectionListener.onEntryAdded(mEntry); + mCollectionListener.onEntryInit(mEntry); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); verify(mNotifInflater).inflateViews(eq(mEntry), any(), any()); mNotifInflater.invokeInflateCallbackForEntry(mEntry); @@ -294,7 +294,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { @Test public void testDoesntFilterInflatedNotifs() { // GIVEN an inflated notification - mCollectionListener.onEntryAdded(mEntry); + mCollectionListener.onEntryInit(mEntry); mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); verify(mNotifInflater).inflateViews(eq(mEntry), any(), any()); mNotifInflater.invokeInflateCallbackForEntry(mEntry); @@ -330,9 +330,9 @@ public class PreparationCoordinatorTest extends SysuiTestCase { mCollectionListener.onEntryInit(entry); } - mCollectionListener.onEntryAdded(summary); + mCollectionListener.onEntryInit(summary); for (NotificationEntry entry : children) { - mCollectionListener.onEntryAdded(entry); + mCollectionListener.onEntryInit(entry); } mBeforeFilterListener.onBeforeFinalizeFilter(List.of(groupEntry)); @@ -393,6 +393,70 @@ public class PreparationCoordinatorTest extends SysuiTestCase { } @Test + public void testNullGroupSummary() { + // GIVEN a newly-posted group with a summary and two children + final GroupEntry group = new GroupEntryBuilder() + .setCreationTime(400) + .setSummary(getNotificationEntryBuilder().setId(1).build()) + .addChild(getNotificationEntryBuilder().setId(2).build()) + .addChild(getNotificationEntryBuilder().setId(3).build()) + .build(); + fireAddEvents(List.of(group)); + final NotificationEntry child0 = group.getChildren().get(0); + final NotificationEntry child1 = group.getChildren().get(1); + mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group)); + + // WHEN the summary is pruned + new GroupEntryBuilder() + .setCreationTime(400) + .addChild(child0) + .addChild(child1) + .build(); + + // WHEN all of the children (but not the summary) finish inflating + mNotifInflater.invokeInflateCallbackForEntry(child0); + mNotifInflater.invokeInflateCallbackForEntry(child1); + + // THEN the entire group is not filtered out + assertFalse(mUninflatedFilter.shouldFilterOut(child0, 401)); + assertFalse(mUninflatedFilter.shouldFilterOut(child1, 401)); + } + + @Test + public void testPartiallyInflatedGroupsAreNotFilteredOutIfSummaryReinflate() { + // GIVEN a newly-posted group with a summary and two children + final String groupKey = "test_reinflate_group"; + final int summaryId = 1; + final GroupEntry group = new GroupEntryBuilder() + .setKey(groupKey) + .setCreationTime(400) + .setSummary(getNotificationEntryBuilder().setId(summaryId).setImportance(1).build()) + .addChild(getNotificationEntryBuilder().setId(2).build()) + .addChild(getNotificationEntryBuilder().setId(3).build()) + .build(); + fireAddEvents(List.of(group)); + final NotificationEntry summary = group.getSummary(); + final NotificationEntry child0 = group.getChildren().get(0); + final NotificationEntry child1 = group.getChildren().get(1); + mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group)); + + // WHEN all of the children (but not the summary) finish inflating + mNotifInflater.invokeInflateCallbackForEntry(child0); + mNotifInflater.invokeInflateCallbackForEntry(child1); + mNotifInflater.invokeInflateCallbackForEntry(summary); + + // WHEN the summary is updated and starts re-inflating + summary.setRanking(new RankingBuilder(summary.getRanking()).setImportance(4).build()); + fireUpdateEvents(summary); + mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group)); + + // THEN the entire group is still not filtered out + assertFalse(mUninflatedFilter.shouldFilterOut(summary, 401)); + assertFalse(mUninflatedFilter.shouldFilterOut(child0, 401)); + assertFalse(mUninflatedFilter.shouldFilterOut(child1, 401)); + } + + @Test public void testCompletedInflatedGroupsAreReleased() { // GIVEN a newly-posted group with a summary and two children final GroupEntry group = new GroupEntryBuilder() @@ -412,7 +476,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase { mNotifInflater.invokeInflateCallbackForEntry(child1); mNotifInflater.invokeInflateCallbackForEntry(summary); - // THEN the entire group is still filtered out + // THEN the entire group is no longer filtered out assertFalse(mUninflatedFilter.shouldFilterOut(summary, 401)); assertFalse(mUninflatedFilter.shouldFilterOut(child0, 401)); assertFalse(mUninflatedFilter.shouldFilterOut(child1, 401)); @@ -494,7 +558,11 @@ public class PreparationCoordinatorTest extends SysuiTestCase { private void fireAddEvents(NotificationEntry entry) { mCollectionListener.onEntryInit(entry); - mCollectionListener.onEntryAdded(entry); + mCollectionListener.onEntryInit(entry); + } + + private void fireUpdateEvents(NotificationEntry entry) { + mCollectionListener.onEntryUpdated(entry); } private static final String TEST_MESSAGE = "TEST_MESSAGE"; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java index 46f630b7db63..ea311da3e20b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java @@ -51,12 +51,14 @@ import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; +import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.NotifPipelineFlags; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.NotificationInterruptEvent; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -97,6 +99,7 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { NotifPipelineFlags mFlags; @Mock KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider; + UiEventLoggerFake mUiEventLoggerFake; @Mock PendingIntent mPendingIntent; @@ -107,6 +110,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); when(mFlags.fullScreenIntentRequiresKeyguard()).thenReturn(false); + mUiEventLoggerFake = new UiEventLoggerFake(); + mNotifInterruptionStateProvider = new NotificationInterruptStateProviderImpl( mContext.getContentResolver(), @@ -120,7 +125,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { mLogger, mMockHandler, mFlags, - mKeyguardNotificationVisibilityProvider); + mKeyguardNotificationVisibilityProvider, + mUiEventLoggerFake); mNotifInterruptionStateProvider.mUseHeadsUp = true; } @@ -442,6 +448,13 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { verify(mLogger, never()).logNoFullscreen(any(), any()); verify(mLogger).logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN"); verify(mLogger, never()).logFullscreen(any(), any()); + + assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1); + UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0); + assertThat(fakeUiEvent.eventId).isEqualTo( + NotificationInterruptEvent.FSI_SUPPRESSED_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR.getId()); + assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid()); + assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName()); } @Test @@ -600,6 +613,13 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { verify(mLogger, never()).logNoFullscreen(any(), any()); verify(mLogger).logNoFullscreenWarning(entry, "Expected not to HUN while not on keyguard"); verify(mLogger, never()).logFullscreen(any(), any()); + + assertThat(mUiEventLoggerFake.numLogs()).isEqualTo(1); + UiEventLoggerFake.FakeUiEvent fakeUiEvent = mUiEventLoggerFake.get(0); + assertThat(fakeUiEvent.eventId).isEqualTo( + NotificationInterruptEvent.FSI_SUPPRESSED_NO_HUN_OR_KEYGUARD.getId()); + assertThat(fakeUiEvent.uid).isEqualTo(entry.getSbn().getUid()); + assertThat(fakeUiEvent.packageName).isEqualTo(entry.getSbn().getPackageName()); } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index ad497a2ec1e1..6de8bd5f3670 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -80,6 +80,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; import com.android.internal.jank.InteractionJankMonitor; +import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.internal.statusbar.IStatusBarService; @@ -98,7 +99,8 @@ import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; -import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -271,7 +273,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase { @Mock private OngoingCallController mOngoingCallController; @Mock private StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager; @Mock private LockscreenShadeTransitionController mLockscreenTransitionController; - @Mock private FeatureFlags mFeatureFlags; @Mock private NotificationVisibilityProvider mVisibilityProvider; @Mock private WallpaperManager mWallpaperManager; @Mock private IWallpaperManager mIWallpaperManager; @@ -296,9 +297,10 @@ public class CentralSurfacesImplTest extends SysuiTestCase { private ShadeController mShadeController; private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); - private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock); - private FakeExecutor mUiBgExecutor = new FakeExecutor(mFakeSystemClock); - private InitController mInitController = new InitController(); + private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock); + private final FakeExecutor mUiBgExecutor = new FakeExecutor(mFakeSystemClock); + private final FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags(); + private final InitController mInitController = new InitController(); private final DumpManager mDumpManager = new DumpManager(); @Before @@ -322,7 +324,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mock(NotificationInterruptLogger.class), new Handler(TestableLooper.get(this).getLooper()), mock(NotifPipelineFlags.class), - mock(KeyguardNotificationVisibilityProvider.class)); + mock(KeyguardNotificationVisibilityProvider.class), + mock(UiEventLogger.class)); mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class)); mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class)); @@ -1017,6 +1020,60 @@ public class CentralSurfacesImplTest extends SysuiTestCase { } @Test + public void collapseShade_callsAnimateCollapsePanels_whenExpanded() { + // GIVEN the shade is expanded + mCentralSurfaces.setPanelExpanded(true); + mCentralSurfaces.setBarStateForTest(StatusBarState.SHADE); + + // WHEN collapseShade is called + mCentralSurfaces.collapseShade(); + + // VERIFY that animateCollapsePanels is called + verify(mShadeController).animateCollapsePanels(); + } + + @Test + public void collapseShade_doesNotCallAnimateCollapsePanels_whenCollapsed() { + // GIVEN the shade is collapsed + mCentralSurfaces.setPanelExpanded(false); + mCentralSurfaces.setBarStateForTest(StatusBarState.SHADE); + + // WHEN collapseShade is called + mCentralSurfaces.collapseShade(); + + // VERIFY that animateCollapsePanels is NOT called + verify(mShadeController, never()).animateCollapsePanels(); + } + + @Test + public void collapseShadeForBugReport_callsAnimateCollapsePanels_whenFlagDisabled() { + // GIVEN the shade is expanded & flag enabled + mCentralSurfaces.setPanelExpanded(true); + mCentralSurfaces.setBarStateForTest(StatusBarState.SHADE); + mFeatureFlags.set(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT, false); + + // WHEN collapseShadeForBugreport is called + mCentralSurfaces.collapseShadeForBugreport(); + + // VERIFY that animateCollapsePanels is called + verify(mShadeController).animateCollapsePanels(); + } + + @Test + public void collapseShadeForBugReport_doesNotCallAnimateCollapsePanels_whenFlagEnabled() { + // GIVEN the shade is expanded & flag enabled + mCentralSurfaces.setPanelExpanded(true); + mCentralSurfaces.setBarStateForTest(StatusBarState.SHADE); + mFeatureFlags.set(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT, true); + + // WHEN collapseShadeForBugreport is called + mCentralSurfaces.collapseShadeForBugreport(); + + // VERIFY that animateCollapsePanels is called + verify(mShadeController, never()).animateCollapsePanels(); + } + + @Test public void deviceStateChange_unfolded_shadeOpen_setsLeaveOpenOnKeyguardHide() { when(mKeyguardStateController.isShowing()).thenReturn(false); setFoldedStates(FOLD_STATE_FOLDED); @@ -1102,7 +1159,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase { NotificationInterruptLogger logger, Handler mainHandler, NotifPipelineFlags flags, - KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) { + KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider, + UiEventLogger uiEventLogger) { super( contentResolver, powerManager, @@ -1115,7 +1173,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase { logger, mainHandler, flags, - keyguardNotificationVisibilityProvider + keyguardNotificationVisibilityProvider, + uiEventLogger ); mUseHeadsUp = true; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt index bf432388ad28..eba3b04f3472 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt @@ -20,7 +20,6 @@ import android.content.Intent import android.os.UserHandle import android.testing.AndroidTestingRunner import android.testing.TestableLooper -import android.view.View import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.flags.FeatureFlags @@ -34,8 +33,8 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock -import org.mockito.Mockito.verify import org.mockito.Mockito.`when` +import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) @@ -91,7 +90,7 @@ class StatusBarUserSwitcherControllerOldImplTest : SysuiTestCase() { fun testStartActivity() { `when`(featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)).thenReturn(false) statusBarUserSwitcherContainer.callOnClick() - verify(userSwitcherDialogController).showDialog(any(View::class.java)) + verify(userSwitcherDialogController).showDialog(any(), any()) `when`(featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)).thenReturn(true) statusBarUserSwitcherContainer.callOnClick() verify(activityStarter).startActivity(any(Intent::class.java), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt index f751afc195b2..2f18ce31217e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/FakeWifiRepository.kt @@ -27,6 +27,9 @@ class FakeWifiRepository : WifiRepository { private val _isWifiEnabled: MutableStateFlow<Boolean> = MutableStateFlow(false) override val isWifiEnabled: StateFlow<Boolean> = _isWifiEnabled + private val _isWifiDefault: MutableStateFlow<Boolean> = MutableStateFlow(false) + override val isWifiDefault: StateFlow<Boolean> = _isWifiDefault + private val _wifiNetwork: MutableStateFlow<WifiNetworkModel> = MutableStateFlow(WifiNetworkModel.Inactive) override val wifiNetwork: StateFlow<WifiNetworkModel> = _wifiNetwork @@ -38,6 +41,10 @@ class FakeWifiRepository : WifiRepository { _isWifiEnabled.value = enabled } + fun setIsWifiDefault(default: Boolean) { + _isWifiDefault.value = default + } + fun setWifiNetwork(wifiNetworkModel: WifiNetworkModel) { _wifiNetwork.value = wifiNetworkModel } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt index 0ba0bd623c39..a64a4bd2e57a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt @@ -222,6 +222,83 @@ class WifiRepositoryImplTest : SysuiTestCase() { } @Test + fun isWifiDefault_initiallyGetsDefault() = runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) + + assertThat(underTest.isWifiDefault.value).isFalse() + + job.cancel() + } + + @Test + fun isWifiDefault_wifiNetwork_isTrue() = runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) + + val wifiInfo = mock<WifiInfo>().apply { + whenever(this.ssid).thenReturn(SSID) + } + + getDefaultNetworkCallback().onCapabilitiesChanged( + NETWORK, + createWifiNetworkCapabilities(wifiInfo) + ) + + assertThat(underTest.isWifiDefault.value).isTrue() + + job.cancel() + } + + @Test + fun isWifiDefault_cellularVcnNetwork_isTrue() = runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) + + val capabilities = mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.transportInfo).thenReturn(VcnTransportInfo(PRIMARY_WIFI_INFO)) + } + + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) + + assertThat(underTest.isWifiDefault.value).isTrue() + + job.cancel() + } + + @Test + fun isWifiDefault_cellularNotVcnNetwork_isFalse() = runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) + + val capabilities = mock<NetworkCapabilities>().apply { + whenever(this.hasTransport(TRANSPORT_CELLULAR)).thenReturn(true) + whenever(this.transportInfo).thenReturn(mock()) + } + + getDefaultNetworkCallback().onCapabilitiesChanged(NETWORK, capabilities) + + assertThat(underTest.isWifiDefault.value).isFalse() + + job.cancel() + } + + @Test + fun isWifiDefault_wifiNetworkLost_isFalse() = runBlocking(IMMEDIATE) { + val job = underTest.isWifiDefault.launchIn(this) + + // First, add a network + getDefaultNetworkCallback() + .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO)) + assertThat(underTest.isWifiDefault.value).isTrue() + + // WHEN the network is lost + getDefaultNetworkCallback().onLost(NETWORK) + + // THEN we update to false + assertThat(underTest.isWifiDefault.value).isFalse() + + job.cancel() + } + + @Test fun wifiNetwork_initiallyGetsDefault() = runBlocking(IMMEDIATE) { var latest: WifiNetworkModel? = null val job = underTest @@ -745,6 +822,12 @@ class WifiRepositoryImplTest : SysuiTestCase() { return callbackCaptor.value!! } + private fun getDefaultNetworkCallback(): ConnectivityManager.NetworkCallback { + val callbackCaptor = argumentCaptor<ConnectivityManager.NetworkCallback>() + verify(connectivityManager).registerDefaultNetworkCallback(callbackCaptor.capture()) + return callbackCaptor.value!! + } + private fun createWifiNetworkCapabilities( wifiInfo: WifiInfo, isValidated: Boolean = true, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt index 39b886af1cb8..71b8bab87d19 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt @@ -178,6 +178,29 @@ class WifiInteractorTest : SysuiTestCase() { } @Test + fun isDefault_matchesRepoIsDefault() = runBlocking(IMMEDIATE) { + var latest: Boolean? = null + val job = underTest + .isDefault + .onEach { latest = it } + .launchIn(this) + + wifiRepository.setIsWifiDefault(true) + yield() + assertThat(latest).isTrue() + + wifiRepository.setIsWifiDefault(false) + yield() + assertThat(latest).isFalse() + + wifiRepository.setIsWifiDefault(true) + yield() + assertThat(latest).isTrue() + + job.cancel() + } + + @Test fun wifiNetwork_matchesRepoWifiNetwork() = runBlocking(IMMEDIATE) { val wifiNetwork = WifiNetworkModel.Active( networkId = 45, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt index e56623f9fea2..7686071206f9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt @@ -88,6 +88,7 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase fun wifiIcon() = runBlocking(IMMEDIATE) { wifiRepository.setIsWifiEnabled(testCase.enabled) + wifiRepository.setIsWifiDefault(testCase.isDefault) connectivityRepository.setForceHiddenIcons( if (testCase.forceHidden) { setOf(ConnectivitySlot.WIFI) @@ -152,6 +153,7 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase val forceHidden: Boolean = false, val alwaysShowIconWhenEnabled: Boolean = false, val hasDataCapabilities: Boolean = true, + val isDefault: Boolean = false, val network: WifiNetworkModel, /** The expected output. Null if we expect the output to be null. */ @@ -162,6 +164,7 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase "forceHidden=$forceHidden, " + "showWhenEnabled=$alwaysShowIconWhenEnabled, " + "hasDataCaps=$hasDataCapabilities, " + + "isDefault=$isDefault, " + "network=$network) then " + "EXPECTED($expected)" } @@ -296,6 +299,46 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase ), ), + // isDefault = true => all Inactive and Active networks shown + TestCase( + isDefault = true, + network = WifiNetworkModel.Inactive, + expected = + Expected( + iconResource = WIFI_NO_NETWORK, + contentDescription = { context -> + "${context.getString(WIFI_NO_CONNECTION)}," + + context.getString(NO_INTERNET) + }, + description = "No network icon", + ), + ), + TestCase( + isDefault = true, + network = WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 3), + expected = + Expected( + iconResource = WIFI_NO_INTERNET_ICONS[3], + contentDescription = { context -> + "${context.getString(WIFI_CONNECTION_STRENGTH[3])}," + + context.getString(NO_INTERNET) + }, + description = "No internet level 3 icon", + ), + ), + TestCase( + isDefault = true, + network = WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 1), + expected = + Expected( + iconResource = WIFI_FULL_ICONS[1], + contentDescription = { context -> + context.getString(WIFI_CONNECTION_STRENGTH[1]) + }, + description = "Full internet level 1 icon", + ), + ), + // network = CarrierMerged => not shown TestCase( network = WifiNetworkModel.CarrierMerged, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt index 3169eef83f07..79633d467b7d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt @@ -76,6 +76,8 @@ class WifiViewModelTest : SysuiTestCase() { scope.cancel() } + // See [WifiViewModelIconParameterizedTest] for additional view model tests. + // Note on testing: [WifiViewModel] exposes 3 different instances of // [LocationBasedWifiViewModel]. In practice, these 3 different instances will get the exact // same data for icon, activity, etc. flows. So, most of these tests will test just one of the diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt index d951f366c595..525d8371c9ff 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplRefactoredTest.kt @@ -110,7 +110,7 @@ class UserRepositoryImplRefactoredTest : UserRepositoryImplTest() { val thirdExpectedValue = setUpUsers( count = 2, - hasGuest = true, + isLastGuestUser = true, selectedIndex = 1, ) underTest.refreshUsers() @@ -121,21 +121,25 @@ class UserRepositoryImplRefactoredTest : UserRepositoryImplTest() { } @Test - fun `refreshUsers - sorts by creation time`() = runSelfCancelingTest { + fun `refreshUsers - sorts by creation time - guest user last`() = runSelfCancelingTest { underTest = create(this) val unsortedUsers = setUpUsers( count = 3, selectedIndex = 0, + isLastGuestUser = true, + ) + unsortedUsers[0].creationTime = 999 + unsortedUsers[1].creationTime = 900 + unsortedUsers[2].creationTime = 950 + val expectedUsers = + listOf( + unsortedUsers[1], + unsortedUsers[0], + unsortedUsers[2], // last because this is the guest ) - unsortedUsers[0].creationTime = 900 - unsortedUsers[1].creationTime = 700 - unsortedUsers[2].creationTime = 999 - val expectedUsers = listOf(unsortedUsers[1], unsortedUsers[0], unsortedUsers[2]) var userInfos: List<UserInfo>? = null - var selectedUserInfo: UserInfo? = null underTest.userInfos.onEach { userInfos = it }.launchIn(this) - underTest.selectedUserInfo.onEach { selectedUserInfo = it }.launchIn(this) underTest.refreshUsers() assertThat(userInfos).isEqualTo(expectedUsers) @@ -143,14 +147,14 @@ class UserRepositoryImplRefactoredTest : UserRepositoryImplTest() { private fun setUpUsers( count: Int, - hasGuest: Boolean = false, + isLastGuestUser: Boolean = false, selectedIndex: Int = 0, ): List<UserInfo> { val userInfos = (0 until count).map { index -> createUserInfo( index, - isGuest = hasGuest && index == count - 1, + isGuest = isLastGuestUser && index == count - 1, ) } whenever(manager.aliveUsers).thenReturn(userInfos) diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt index 1540f8552002..97571b23be56 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorRefactoredTest.kt @@ -28,6 +28,7 @@ import androidx.test.filters.SmallTest import com.android.internal.R.drawable.ic_account_circle import com.android.systemui.R import com.android.systemui.common.shared.model.Text +import com.android.systemui.qs.user.UserSwitchDialogController import com.android.systemui.user.data.model.UserSwitcherSettingsModel import com.android.systemui.user.data.source.UserRecord import com.android.systemui.user.domain.model.ShowDialogRequestModel @@ -316,14 +317,16 @@ class UserInteractorRefactoredTest : UserInteractorTest() { keyguardRepository.setKeyguardShowing(false) var dialogRequest: ShowDialogRequestModel? = null val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this) + val dialogShower: UserSwitchDialogController.DialogShower = mock() - underTest.executeAction(UserActionModel.ADD_USER) + underTest.executeAction(UserActionModel.ADD_USER, dialogShower) assertThat(dialogRequest) .isEqualTo( ShowDialogRequestModel.ShowAddUserDialog( userHandle = userInfos[0].userHandle, isKeyguardShowing = false, showEphemeralMessage = false, + dialogShower = dialogShower, ) ) 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 09da52e7685c..fa7ebf6a2449 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -80,6 +80,7 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; +import com.android.internal.logging.UiEventLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.AuthController; @@ -91,6 +92,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shade.NotificationShadeWindowControllerImpl; import com.android.systemui.shade.NotificationShadeWindowView; import com.android.systemui.shade.ShadeController; +import com.android.systemui.shade.ShadeExpansionStateManager; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.RankingBuilder; @@ -190,6 +192,8 @@ public class BubblesTest extends SysuiTestCase { private NotificationShadeWindowView mNotificationShadeWindowView; @Mock private AuthController mAuthController; + @Mock + private ShadeExpansionStateManager mShadeExpansionStateManager; private SysUiState mSysUiState; private boolean mSysUiStateBubblesExpanded; @@ -290,7 +294,7 @@ public class BubblesTest extends SysuiTestCase { mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController, mColorExtractor, mDumpManager, mKeyguardStateController, - mScreenOffAnimationController, mAuthController); + mScreenOffAnimationController, mAuthController, mShadeExpansionStateManager); mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); mNotificationShadeWindowController.attach(); @@ -343,7 +347,8 @@ public class BubblesTest extends SysuiTestCase { mock(NotificationInterruptLogger.class), mock(Handler.class), mock(NotifPipelineFlags.class), - mock(KeyguardNotificationVisibilityProvider.class) + mock(KeyguardNotificationVisibilityProvider.class), + mock(UiEventLogger.class) ); when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor); mBubbleController = new TestableBubbleController( diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java index 9635faf6e858..e5316bc83a12 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableNotificationInterruptStateProviderImpl.java @@ -22,6 +22,7 @@ import android.os.Handler; import android.os.PowerManager; import android.service.dreams.IDreamManager; +import com.android.internal.logging.UiEventLogger; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.NotifPipelineFlags; import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider; @@ -46,7 +47,8 @@ public class TestableNotificationInterruptStateProviderImpl NotificationInterruptLogger logger, Handler mainHandler, NotifPipelineFlags flags, - KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider) { + KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider, + UiEventLogger uiEventLogger) { super(contentResolver, powerManager, dreamManager, @@ -58,7 +60,8 @@ public class TestableNotificationInterruptStateProviderImpl logger, mainHandler, flags, - keyguardNotificationVisibilityProvider); + keyguardNotificationVisibilityProvider, + uiEventLogger); mUseHeadsUp = true; } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt index 527258579372..c33ce5d9484d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/FakeFgsManagerController.kt @@ -16,7 +16,7 @@ package com.android.systemui.qs -import android.view.View +import com.android.systemui.animation.Expandable import com.android.systemui.qs.FgsManagerController.OnDialogDismissedListener import com.android.systemui.qs.FgsManagerController.OnNumberOfPackagesChangedListener import kotlinx.coroutines.flow.MutableStateFlow @@ -54,7 +54,7 @@ class FakeFgsManagerController( override fun init() {} - override fun showDialog(viewLaunchedFrom: View?) {} + override fun showDialog(expandable: Expandable?) {} override fun addOnNumberOfPackagesChangedListener(listener: OnNumberOfPackagesChangedListener) { numRunningPackagesListeners.add(listener) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt index 2a9aeddc9aa8..325da4ead666 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt @@ -57,7 +57,6 @@ import com.android.systemui.statusbar.policy.UserSwitcherController import com.android.systemui.util.mockito.mock import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.GlobalSettings -import com.android.systemui.util.time.FakeSystemClock import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.test.TestCoroutineDispatcher @@ -68,7 +67,6 @@ import kotlinx.coroutines.test.TestCoroutineDispatcher class FooterActionsTestUtils( private val context: Context, private val testableLooper: TestableLooper, - private val fakeClock: FakeSystemClock = FakeSystemClock(), ) { /** Enable or disable the user switcher in the settings. */ fun setUserSwitcherEnabled(settings: GlobalSettings, enabled: Boolean, userId: Int) { diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 38237fa8eabd..23cacf3c54cf 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -866,6 +866,33 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } @Override + public void setAppWidgetHidden(String callingPackage, int hostId) { + final int userId = UserHandle.getCallingUserId(); + + if (DEBUG) { + Slog.i(TAG, "setAppWidgetHidden() " + userId); + } + + mSecurityPolicy.enforceCallFromPackage(callingPackage); + + synchronized (mLock) { + ensureGroupStateLoadedLocked(userId, /* enforceUserUnlockingOrUnlocked */false); + + HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage); + Host host = lookupHostLocked(id); + + if (host != null) { + try { + mAppOpsManagerInternal.updateAppWidgetVisibility(host.getWidgetUids(), false); + } catch (NullPointerException e) { + Slog.e(TAG, "setAppWidgetHidden(): Getting host uids: " + host.toString(), e); + throw e; + } + } + } + } + + @Override public void deleteAppWidgetId(String callingPackage, int appWidgetId) { final int userId = UserHandle.getCallingUserId(); diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java index 6759d79eedca..9a190316f4eb 100644 --- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java +++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java @@ -32,7 +32,6 @@ import android.os.Handler; import android.os.PowerWhitelistManager; import android.os.UserHandle; import android.text.TextUtils; -import android.util.EventLog; import android.util.Log; import android.view.KeyEvent; @@ -118,12 +117,6 @@ final class MediaButtonReceiverHolder { int componentType = getComponentType(pendingIntent); ComponentName componentName = getComponentName(pendingIntent, componentType); if (componentName != null) { - if (!TextUtils.equals(componentName.getPackageName(), sessionPackageName)) { - EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging - throw new IllegalArgumentException("ComponentName does not belong to " - + "sessionPackageName. sessionPackageName = " + sessionPackageName - + ", ComponentName pkg = " + componentName.getPackageName()); - } return new MediaButtonReceiverHolder(userId, pendingIntent, componentName, componentType); } diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index b8131a8ee5b5..604e8f3949f4 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -52,8 +52,6 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; -import android.text.TextUtils; -import android.util.EventLog; import android.util.Log; import android.view.KeyEvent; @@ -940,14 +938,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR @Override public void setMediaButtonReceiver(PendingIntent pi, String sessionPackageName) throws RemoteException { - //mPackageName has been verified in MediaSessionService.enforcePackageName(). - if (!TextUtils.equals(sessionPackageName, mPackageName)) { - EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging - throw new IllegalArgumentException("sessionPackageName name does not match " - + "package name provided to MediaSessionRecord. sessionPackageName = " - + sessionPackageName + ", pkg = " - + mPackageName); - } final long token = Binder.clearCallingIdentity(); try { if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER) @@ -966,15 +956,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR public void setMediaButtonBroadcastReceiver(ComponentName receiver) throws RemoteException { final long token = Binder.clearCallingIdentity(); try { - //mPackageName has been verified in MediaSessionService.enforcePackageName(). - if (receiver != null && !TextUtils.equals( - mPackageName, receiver.getPackageName())) { - EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging - throw new IllegalArgumentException("receiver does not belong to " - + "package name provided to MediaSessionRecord. Pkg = " + mPackageName - + ", Receiver Pkg = " + receiver.getPackageName()); - } - if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER) != 0) { return; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index fd1fdce4cf77..a55b11838c7b 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -61,6 +61,7 @@ import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_TELECOM; import static android.content.pm.PackageManager.FEATURE_TELEVISION; import static android.content.pm.PackageManager.MATCH_ALL; +import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -10633,10 +10634,18 @@ public class NotificationManagerService extends SystemService { private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>(); ArrayMap<Pair<ComponentName, Integer>, NotificationListenerFilter> mRequestedNotificationListeners = new ArrayMap<>(); + private final boolean mIsHeadlessSystemUserMode; public NotificationListeners(Context context, Object lock, UserProfiles userProfiles, IPackageManager pm) { + this(context, lock, userProfiles, pm, UserManager.isHeadlessSystemUserMode()); + } + + @VisibleForTesting + public NotificationListeners(Context context, Object lock, UserProfiles userProfiles, + IPackageManager pm, boolean isHeadlessSystemUserMode) { super(context, lock, userProfiles, pm); + this.mIsHeadlessSystemUserMode = isHeadlessSystemUserMode; } @Override @@ -10661,10 +10670,16 @@ public class NotificationManagerService extends SystemService { if (TextUtils.isEmpty(listeners[i])) { continue; } + int packageQueryFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; + // In the headless system user mode, packages might not be installed for the + // system user. Match packages for any user since apps can be installed only for + // non-system users and would be considering uninstalled for the system user. + if (mIsHeadlessSystemUserMode) { + packageQueryFlags += MATCH_ANY_USER; + } ArraySet<ComponentName> approvedListeners = - this.queryPackageForServices(listeners[i], - MATCH_DIRECT_BOOT_AWARE - | MATCH_DIRECT_BOOT_UNAWARE, USER_SYSTEM); + this.queryPackageForServices(listeners[i], packageQueryFlags, + USER_SYSTEM); for (int k = 0; k < approvedListeners.size(); k++) { ComponentName cn = approvedListeners.valueAt(k); addDefaultComponentOrPackage(cn.flattenToString()); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 653b51a95993..3df8f584fef1 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -2253,6 +2253,25 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + boolean proto = false; + for (int i = 0; i < args.length; i++) { + if ("--proto".equals(args[i])) { + proto = true; + } + } + if (proto) { + if (mBar == null) return; + try (TransferPipe tp = new TransferPipe()) { + // Sending the command to the remote, which needs to execute async to avoid blocking + // See Binder#dumpAsync() for inspiration + mBar.dumpProto(args, tp.getWriteFd()); + // Times out after 5s + tp.go(fd); + } catch (Throwable t) { + Slog.e(TAG, "Error sending command to IStatusBar", t); + } + return; + } synchronized (mLock) { for (int i = 0; i < mDisplayUiState.size(); i++) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 2ee4af56d320..46141940a907 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1823,7 +1823,8 @@ public final class SystemServer implements Dumpable { t.traceBegin("StartStatusBarManagerService"); try { statusBar = new StatusBarManagerService(context); - ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); + ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar, false, + DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO); } catch (Throwable e) { reportWtf("starting StatusBarManagerService", e); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java index c5131c8f8c1d..101a5cb49f9b 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java @@ -15,6 +15,7 @@ */ package com.android.server.notification; +import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS; import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING; @@ -30,9 +31,11 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.intThat; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -49,6 +52,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.pm.VersionedPackage; +import android.content.res.Resources; import android.os.Bundle; import android.os.UserHandle; import android.service.notification.NotificationListenerFilter; @@ -69,6 +73,7 @@ import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.internal.util.reflection.FieldSetter; @@ -77,6 +82,7 @@ import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.util.Arrays; import java.util.List; public class NotificationListenersTest extends UiServiceTestCase { @@ -85,6 +91,8 @@ public class NotificationListenersTest extends UiServiceTestCase { private PackageManager mPm; @Mock private IPackageManager miPm; + @Mock + private Resources mResources; @Mock NotificationManagerService mNm; @@ -96,7 +104,8 @@ public class NotificationListenersTest extends UiServiceTestCase { private ComponentName mCn1 = new ComponentName("pkg", "pkg.cmp"); private ComponentName mCn2 = new ComponentName("pkg2", "pkg2.cmp2"); - + private ComponentName mUninstalledComponent = new ComponentName("pkg3", + "pkg3.NotificationListenerService"); @Before public void setUp() throws Exception { @@ -111,7 +120,7 @@ public class NotificationListenersTest extends UiServiceTestCase { @Test public void testReadExtraTag() throws Exception { - String xml = "<" + TAG_REQUESTED_LISTENERS+ ">" + String xml = "<" + TAG_REQUESTED_LISTENERS + ">" + "<listener component=\"" + mCn1.flattenToString() + "\" user=\"0\">" + "<allowed types=\"7\" />" + "</listener>" @@ -131,11 +140,55 @@ public class NotificationListenersTest extends UiServiceTestCase { } @Test + public void loadDefaultsFromConfig_forHeadlessSystemUser_loadUninstalled() throws Exception { + // setup with headless system user mode + mListeners = spy(mNm.new NotificationListeners( + mContext, new Object(), mock(ManagedServices.UserProfiles.class), miPm, + /* isHeadlessSystemUserMode= */ true)); + mockDefaultListenerConfigForUninstalledComponent(mUninstalledComponent); + + mListeners.loadDefaultsFromConfig(); + + assertThat(mListeners.getDefaultComponents()).contains(mUninstalledComponent); + } + + @Test + public void loadDefaultsFromConfig_forNonHeadlessSystemUser_ignoreUninstalled() + throws Exception { + // setup without headless system user mode + mListeners = spy(mNm.new NotificationListeners( + mContext, new Object(), mock(ManagedServices.UserProfiles.class), miPm, + /* isHeadlessSystemUserMode= */ false)); + mockDefaultListenerConfigForUninstalledComponent(mUninstalledComponent); + + mListeners.loadDefaultsFromConfig(); + + assertThat(mListeners.getDefaultComponents()).doesNotContain(mUninstalledComponent); + } + + private void mockDefaultListenerConfigForUninstalledComponent(ComponentName componentName) { + ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(componentName)); + when(mResources + .getString( + com.android.internal.R.string.config_defaultListenerAccessPackages)) + .thenReturn(componentName.getPackageName()); + when(mContext.getResources()).thenReturn(mResources); + doReturn(components).when(mListeners).queryPackageForServices( + eq(componentName.getPackageName()), + intThat(hasIntBitFlag(MATCH_ANY_USER)), + anyInt()); + } + + public static ArgumentMatcher<Integer> hasIntBitFlag(int flag) { + return arg -> arg != null && ((arg & flag) == flag); + } + + @Test public void testWriteExtraTag() throws Exception { NotificationListenerFilter nlf = new NotificationListenerFilter(7, new ArraySet<>()); VersionedPackage a1 = new VersionedPackage("pkg1", 243); NotificationListenerFilter nlf2 = - new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[] {a1})); + new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[]{a1})); mListeners.setNotificationListenerFilter(Pair.create(mCn1, 0), nlf); mListeners.setNotificationListenerFilter(Pair.create(mCn2, 10), nlf2); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java deleted file mode 100644 index d7650420788c..000000000000 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (C) 2017 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.notification; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.app.ActivityManager; -import android.app.Notification; -import android.app.PendingIntent; -import android.app.Person; -import android.app.RemoteInput; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.Typeface; -import android.graphics.drawable.Icon; -import android.net.Uri; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.style.StyleSpan; -import android.util.Pair; -import android.widget.RemoteViews; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.server.UiServiceTestCase; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NotificationTest extends UiServiceTestCase { - - @Mock - ActivityManager mAm; - - @Mock - Resources mResources; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testDoesNotStripsExtenders() { - Notification.Builder nb = new Notification.Builder(mContext, "channel"); - nb.extend(new Notification.CarExtender().setColor(Color.RED)); - nb.extend(new Notification.TvExtender().setChannelId("different channel")); - nb.extend(new Notification.WearableExtender().setDismissalId("dismiss")); - Notification before = nb.build(); - Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before); - - assertTrue(before == after); - - assertEquals("different channel", new Notification.TvExtender(before).getChannelId()); - assertEquals(Color.RED, new Notification.CarExtender(before).getColor()); - assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId()); - } - - @Test - public void testStyleChangeVisiblyDifferent_noStyles() { - Notification.Builder n1 = new Notification.Builder(mContext, "test"); - Notification.Builder n2 = new Notification.Builder(mContext, "test"); - - assertFalse(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); - } - - @Test - public void testStyleChangeVisiblyDifferent_noStyleToStyle() { - Notification.Builder n1 = new Notification.Builder(mContext, "test"); - Notification.Builder n2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.BigTextStyle()); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); - } - - @Test - public void testStyleChangeVisiblyDifferent_styleToNoStyle() { - Notification.Builder n2 = new Notification.Builder(mContext, "test"); - Notification.Builder n1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.BigTextStyle()); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); - } - - @Test - public void testStyleChangeVisiblyDifferent_changeStyle() { - Notification.Builder n1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.InboxStyle()); - Notification.Builder n2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.BigTextStyle()); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2)); - } - - @Test - public void testInboxTextChange() { - Notification.Builder nInbox1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.InboxStyle().addLine("a").addLine("b")); - Notification.Builder nInbox2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.InboxStyle().addLine("b").addLine("c")); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nInbox1, nInbox2)); - } - - @Test - public void testBigTextTextChange() { - Notification.Builder nBigText1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.BigTextStyle().bigText("something")); - Notification.Builder nBigText2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.BigTextStyle().bigText("else")); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nBigText1, nBigText2)); - } - - @Test - public void testBigPictureChange() { - Bitmap bitA = mock(Bitmap.class); - when(bitA.getGenerationId()).thenReturn(100); - Bitmap bitB = mock(Bitmap.class); - when(bitB.getGenerationId()).thenReturn(200); - - Notification.Builder nBigPic1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.BigPictureStyle().bigPicture(bitA)); - Notification.Builder nBigPic2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.BigPictureStyle().bigPicture(bitB)); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nBigPic1, nBigPic2)); - } - - @Test - public void testMessagingChange_text() { - Notification.Builder nM1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message( - "a", 100, mock(Person.class)))); - Notification.Builder nM2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message( - "a", 100, mock(Person.class))) - .addMessage(new Notification.MessagingStyle.Message( - "b", 100, mock(Person.class))) - ); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); - } - - @Test - public void testMessagingChange_data() { - Notification.Builder nM1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message( - "a", 100, mock(Person.class)) - .setData("text", mock(Uri.class)))); - Notification.Builder nM2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message( - "a", 100, mock(Person.class)))); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); - } - - @Test - public void testMessagingChange_sender() { - Person a = mock(Person.class); - when(a.getName()).thenReturn("A"); - Person b = mock(Person.class); - when(b.getName()).thenReturn("b"); - Notification.Builder nM1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message("a", 100, b))); - Notification.Builder nM2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message("a", 100, a))); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); - } - - @Test - public void testMessagingChange_key() { - Person a = mock(Person.class); - when(a.getKey()).thenReturn("A"); - Person b = mock(Person.class); - when(b.getKey()).thenReturn("b"); - Notification.Builder nM1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message("a", 100, a))); - Notification.Builder nM2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message("a", 100, b))); - - assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); - } - - @Test - public void testMessagingChange_ignoreTimeChange() { - Notification.Builder nM1 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message( - "a", 100, mock(Person.class)))); - Notification.Builder nM2 = new Notification.Builder(mContext, "test") - .setStyle(new Notification.MessagingStyle("") - .addMessage(new Notification.MessagingStyle.Message( - "a", 1000, mock(Person.class))) - ); - - assertFalse(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2)); - } - - @Test - public void testRemoteViews_nullChange() { - Notification.Builder n1 = new Notification.Builder(mContext, "test") - .setContent(mock(RemoteViews.class)); - Notification.Builder n2 = new Notification.Builder(mContext, "test"); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test"); - n2 = new Notification.Builder(mContext, "test") - .setContent(mock(RemoteViews.class)); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test") - .setCustomBigContentView(mock(RemoteViews.class)); - n2 = new Notification.Builder(mContext, "test"); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test"); - n2 = new Notification.Builder(mContext, "test") - .setCustomBigContentView(mock(RemoteViews.class)); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test"); - n2 = new Notification.Builder(mContext, "test"); - assertFalse(Notification.areRemoteViewsChanged(n1, n2)); - } - - @Test - public void testRemoteViews_layoutChange() { - RemoteViews a = mock(RemoteViews.class); - when(a.getLayoutId()).thenReturn(234); - RemoteViews b = mock(RemoteViews.class); - when(b.getLayoutId()).thenReturn(189); - - Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); - Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); - n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); - n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - } - - @Test - public void testRemoteViews_layoutSame() { - RemoteViews a = mock(RemoteViews.class); - when(a.getLayoutId()).thenReturn(234); - RemoteViews b = mock(RemoteViews.class); - when(b.getLayoutId()).thenReturn(234); - - Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); - Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); - assertFalse(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); - n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); - assertFalse(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); - n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); - assertFalse(Notification.areRemoteViewsChanged(n1, n2)); - } - - @Test - public void testRemoteViews_sequenceChange() { - RemoteViews a = mock(RemoteViews.class); - when(a.getLayoutId()).thenReturn(234); - when(a.getSequenceNumber()).thenReturn(1); - RemoteViews b = mock(RemoteViews.class); - when(b.getLayoutId()).thenReturn(234); - when(b.getSequenceNumber()).thenReturn(2); - - Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); - Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); - n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); - n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); - assertTrue(Notification.areRemoteViewsChanged(n1, n2)); - } - - @Test - public void testRemoteViews_sequenceSame() { - RemoteViews a = mock(RemoteViews.class); - when(a.getLayoutId()).thenReturn(234); - when(a.getSequenceNumber()).thenReturn(1); - RemoteViews b = mock(RemoteViews.class); - when(b.getLayoutId()).thenReturn(234); - when(b.getSequenceNumber()).thenReturn(1); - - Notification.Builder n1 = new Notification.Builder(mContext, "test").setContent(a); - Notification.Builder n2 = new Notification.Builder(mContext, "test").setContent(b); - assertFalse(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test").setCustomBigContentView(a); - n2 = new Notification.Builder(mContext, "test").setCustomBigContentView(b); - assertFalse(Notification.areRemoteViewsChanged(n1, n2)); - - n1 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(a); - n2 = new Notification.Builder(mContext, "test").setCustomHeadsUpContentView(b); - assertFalse(Notification.areRemoteViewsChanged(n1, n2)); - } - - @Test - public void testActionsDifferent_null() { - Notification n1 = new Notification.Builder(mContext, "test") - .build(); - Notification n2 = new Notification.Builder(mContext, "test") - .build(); - - assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); - } - - @Test - public void testActionsDifferentSame() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - - Notification n1 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) - .build(); - Notification n2 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) - .build(); - - assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); - } - - @Test - public void testActionsDifferentText() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - - Notification n1 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) - .build(); - Notification n2 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 2", intent).build()) - .build(); - - assertTrue(Notification.areActionsVisiblyDifferent(n1, n2)); - } - - @Test - public void testActionsDifferentSpannables() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - - Notification n1 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, - new SpannableStringBuilder().append("test1", - new StyleSpan(Typeface.BOLD), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE), - intent).build()) - .build(); - Notification n2 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "test1", intent).build()) - .build(); - - assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); - } - - @Test - public void testActionsDifferentNumber() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - - Notification n1 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) - .build(); - Notification n2 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build()) - .addAction(new Notification.Action.Builder(icon, "TEXT 2", intent).build()) - .build(); - - assertTrue(Notification.areActionsVisiblyDifferent(n1, n2)); - } - - @Test - public void testActionsDifferentIntent() { - PendingIntent intent1 = mock(PendingIntent.class); - PendingIntent intent2 = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - - Notification n1 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent1).build()) - .build(); - Notification n2 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent2).build()) - .build(); - - assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); - } - - @Test - public void testActionsIgnoresRemoteInputs() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - - Notification n1 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) - .addRemoteInput(new RemoteInput.Builder("a") - .setChoices(new CharSequence[] {"i", "m"}) - .build()) - .build()) - .build(); - Notification n2 = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) - .addRemoteInput(new RemoteInput.Builder("a") - .setChoices(new CharSequence[] {"t", "m"}) - .build()) - .build()) - .build(); - - assertFalse(Notification.areActionsVisiblyDifferent(n1, n2)); - } - - @Test - public void testFreeformRemoteInputActionPair_noRemoteInput() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - Notification notification = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) - .build()) - .build(); - assertNull(notification.findRemoteInputActionPair(false)); - } - - @Test - public void testFreeformRemoteInputActionPair_hasRemoteInput() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - - RemoteInput remoteInput = new RemoteInput.Builder("a").build(); - - Notification.Action actionWithRemoteInput = - new Notification.Action.Builder(icon, "TEXT 1", intent) - .addRemoteInput(remoteInput) - .addRemoteInput(remoteInput) - .build(); - - Notification.Action actionWithoutRemoteInput = - new Notification.Action.Builder(icon, "TEXT 2", intent) - .build(); - - Notification notification = new Notification.Builder(mContext, "test") - .addAction(actionWithoutRemoteInput) - .addAction(actionWithRemoteInput) - .build(); - - Pair<RemoteInput, Notification.Action> remoteInputActionPair = - notification.findRemoteInputActionPair(false); - - assertNotNull(remoteInputActionPair); - assertEquals(remoteInput, remoteInputActionPair.first); - assertEquals(actionWithRemoteInput, remoteInputActionPair.second); - } - - @Test - public void testFreeformRemoteInputActionPair_requestFreeform_noFreeformRemoteInput() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - Notification notification = new Notification.Builder(mContext, "test") - .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent) - .addRemoteInput( - new RemoteInput.Builder("a") - .setAllowFreeFormInput(false).build()) - .build()) - .build(); - assertNull(notification.findRemoteInputActionPair(true)); - } - - @Test - public void testFreeformRemoteInputActionPair_requestFreeform_hasFreeformRemoteInput() { - PendingIntent intent = mock(PendingIntent.class); - Icon icon = mock(Icon.class); - - RemoteInput remoteInput = - new RemoteInput.Builder("a").setAllowFreeFormInput(false).build(); - RemoteInput freeformRemoteInput = - new RemoteInput.Builder("b").setAllowFreeFormInput(true).build(); - - Notification.Action actionWithFreeformRemoteInput = - new Notification.Action.Builder(icon, "TEXT 1", intent) - .addRemoteInput(remoteInput) - .addRemoteInput(freeformRemoteInput) - .build(); - - Notification.Action actionWithoutFreeformRemoteInput = - new Notification.Action.Builder(icon, "TEXT 2", intent) - .addRemoteInput(remoteInput) - .build(); - - Notification notification = new Notification.Builder(mContext, "test") - .addAction(actionWithoutFreeformRemoteInput) - .addAction(actionWithFreeformRemoteInput) - .build(); - - Pair<RemoteInput, Notification.Action> remoteInputActionPair = - notification.findRemoteInputActionPair(true); - - assertNotNull(remoteInputActionPair); - assertEquals(freeformRemoteInput, remoteInputActionPair.first); - assertEquals(actionWithFreeformRemoteInput, remoteInputActionPair.second); - } -} - diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 3da47110fb49..352d8d115b6a 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -136,9 +136,6 @@ public class VoiceInteractionManagerService extends SystemService { private final RemoteCallbackList<IVoiceInteractionSessionListener> mVoiceInteractionSessionListeners = new RemoteCallbackList<>(); - // TODO(b/226201975): remove once RoleService supports pre-created users - private final ArrayList<UserHandle> mIgnoredPreCreatedUsers = new ArrayList<>(); - public VoiceInteractionManagerService(Context context) { super(context); mContext = context; @@ -308,24 +305,14 @@ public class VoiceInteractionManagerService extends SystemService { return hotwordDetectionConnection.mIdentity; } + // TODO(b/226201975): remove this method once RoleService supports pre-created users @Override public void onPreCreatedUserConversion(int userId) { - Slogf.d(TAG, "onPreCreatedUserConversion(%d)", userId); - - for (int i = 0; i < mIgnoredPreCreatedUsers.size(); i++) { - UserHandle preCreatedUser = mIgnoredPreCreatedUsers.get(i); - if (preCreatedUser.getIdentifier() == userId) { - Slogf.d(TAG, "Updating role on pre-created user %d", userId); - mServiceStub.mRoleObserver.onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, - preCreatedUser); - mIgnoredPreCreatedUsers.remove(i); - return; - } - } - Slogf.w(TAG, "onPreCreatedUserConversion(%d): not available on " - + "mIgnoredPreCreatedUserIds (%s)", userId, mIgnoredPreCreatedUsers); + Slogf.d(TAG, "onPreCreatedUserConversion(%d): calling onRoleHoldersChanged() again", + userId); + mServiceStub.mRoleObserver.onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, + UserHandle.of(userId)); } - } // implementation entry point and binder service @@ -807,8 +794,10 @@ public class VoiceInteractionManagerService extends SystemService { if (TextUtils.isEmpty(curInteractor)) { return null; } - if (DEBUG) Slog.d(TAG, "getCurInteractor curInteractor=" + curInteractor + if (DEBUG) { + Slog.d(TAG, "getCurInteractor curInteractor=" + curInteractor + " user=" + userHandle); + } return ComponentName.unflattenFromString(curInteractor); } @@ -816,8 +805,9 @@ public class VoiceInteractionManagerService extends SystemService { Settings.Secure.putStringForUser(mContext.getContentResolver(), Settings.Secure.VOICE_INTERACTION_SERVICE, comp != null ? comp.flattenToShortString() : "", userHandle); - if (DEBUG) Slog.d(TAG, "setCurInteractor comp=" + comp - + " user=" + userHandle); + if (DEBUG) { + Slog.d(TAG, "setCurInteractor comp=" + comp + " user=" + userHandle); + } } ComponentName findAvailRecognizer(String prefPackage, int userHandle) { @@ -1912,7 +1902,6 @@ public class VoiceInteractionManagerService extends SystemService { pw.println(" mTemporarilyDisabled: " + mTemporarilyDisabled); pw.println(" mCurUser: " + mCurUser); pw.println(" mCurUserSupported: " + mCurUserSupported); - pw.println(" mIgnoredPreCreatedUsers: " + mIgnoredPreCreatedUsers); dumpSupportedUsers(pw, " "); mDbHelper.dump(pw); if (mImpl == null) { @@ -2026,6 +2015,11 @@ public class VoiceInteractionManagerService extends SystemService { List<String> roleHolders = mRm.getRoleHoldersAsUser(roleName, user); + if (DEBUG) { + Slogf.d(TAG, "onRoleHoldersChanged(%s, %s): roleHolders=%s", roleName, user, + roleHolders); + } + // TODO(b/226201975): this method is beling called when a pre-created user is added, // at which point it doesn't have any role holders. But it's not called again when // the actual user is added (i.e., when the pre-created user is converted), so we @@ -2036,9 +2030,9 @@ public class VoiceInteractionManagerService extends SystemService { if (roleHolders.isEmpty()) { UserInfo userInfo = mUserManagerInternal.getUserInfo(user.getIdentifier()); if (userInfo != null && userInfo.preCreated) { - Slogf.d(TAG, "onRoleHoldersChanged(): ignoring pre-created user %s for now", - userInfo.toFullString()); - mIgnoredPreCreatedUsers.add(user); + Slogf.d(TAG, "onRoleHoldersChanged(): ignoring pre-created user %s for now," + + " this method will be called again when it's converted to a real" + + " user", userInfo.toFullString()); return; } } |